git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* git installation fails in home directory on ubuntu 12.04
@ 2012-09-18 11:23  3% Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2012-09-18 11:23 UTC (permalink / raw)
  To: Junio C Hamano, git

So I did
git fetch
git rebase
git describe
v1.7.12-503-g5976753

./configure --prefix=/home/sb
make
make install
    GEN perl/PM.stamp
    SUBDIR gitweb
    SUBDIR ../
    SUBDIR perl
make[1]: `perl.mak' is up to date.
make[2]: `GIT-VERSION-FILE' is up to date.
    GEN git-instaweb
    SUBDIR git-gui
    SUBDIR gitk-git
make[1]: Nothing to be done for `all'.
    SUBDIR perl
    SUBDIR git_remote_helpers
    SUBDIR templates
install -d -m 755 '/home/sb/bin'
install -d -m 755 '/home/sb/libexec/git-core'
install   git-credential-store git-daemon git-fast-import
git-http-backend git-imap-send git-sh-i18n--envsubst git-shell
git-show-index git-upload-pack git-http-fetch git-http-push
git-credential-cache git-credential-cache--daemon git-remote-http
git-remote-https git-remote-ftp git-remote-ftps git-am git-bisect
git-difftool--helper git-filter-branch git-lost-found git-merge-octopus
git-merge-one-file git-merge-resolve git-mergetool git-pull
git-quiltimport git-rebase git-repack git-request-pull git-stash
git-submodule git-web--browse git-add--interactive git-difftool
git-archimport git-cvsexportcommit git-cvsimport git-cvsserver
git-relink git-send-email git-svn git-remote-testgit git-p4 git-instaweb
'/home/sb/libexec/git-core'
install -m 644  git-mergetool--lib git-parse-remote git-rebase--am
git-rebase--interactive git-rebase--merge git-sh-setup git-sh-i18n
'/home/sb/libexec/git-core'
install git git-upload-pack git-receive-pack git-upload-archive
git-shell git-cvsserver '/home/sb/bin'
make -C templates DESTDIR='' install
make[1]: Entering directory `/home/sb/OSS/git/templates'
install -d -m 755 '/home/sb/share/git-core/templates'
(cd blt && tar cf - .) | \
	(cd '/home/sb/share/git-core/templates' && umask 022 && tar xof -)
make[1]: Leaving directory `/home/sb/OSS/git/templates'
install -d -m 755 '/home/sb/libexec/git-core/mergetools'
install -m 644 mergetools/* '/home/sb/libexec/git-core/mergetools'
install -d -m 755 '/home/sb/share/locale'
(cd po/build/locale && tar cf - .) | \
	(cd '/home/sb/share/locale' && umask 022 && tar xof -)
make -C perl prefix='/home/sb' DESTDIR='' install
make[1]: Entering directory `/home/sb/OSS/git/perl'
make[2]: Entering directory `/home/sb/OSS/git/perl'
Appending installation info to /usr/local/lib/perl/5.14.2/perllocal.pod
mkdir /usr/local/lib/perl: Permission denied at
/usr/share/perl/5.14/ExtUtils/Command.pm line 288
make[2]: [doc_site_install] Error 13 (ignored)
/bin/sh: 1: cannot create /usr/local/lib/perl/5.14.2/perllocal.pod:
Directory nonexistent
make[2]: [doc_site_install] Error 2 (ignored)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ERROR: Can't create '/usr/local/share/man/man3'
mkdir /usr/local/share/man/man3: Permission denied at
/usr/share/perl/5.14/ExtUtils/Install.pm line 494

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 at -e line 1
make[2]: *** [pure_site_install] Error 13
make[2]: Target `install' not remade because of errors.
make[2]: Leaving directory `/home/sb/OSS/git/perl'
make[1]: *** [install] Error 2
make[1]: Leaving directory `/home/sb/OSS/git/perl'
make: *** [install] Error 2

^ permalink raw reply	[relevance 3%]

* [PATCH] status_printf_ln: Suppress false positive warnings of empty format string.
@ 2013-07-19 14:08  5% Stefan Beller
  2013-07-19 16:01  2% ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2013-07-19 14:08 UTC (permalink / raw)
  To: peff, gitster, git; +Cc: Stefan Beller

This is a response to 8dd0ee823f1829a3aa228c3c73e31de5c89b5317.

Instead of having an empty string as format for the printf like function
status_printf_ln, we could insert an empty string into the format
parameter.

A similar fixup commit is found in linux (2e4c332913b5), but there
the empty string is replaced by a string containing one whitespace.

To determine, which approach is better I setup 2 test programs, which
either have a whitespace format (" ") or the empty string ("%s", ""),
looking like:
-
	#include <stdlib.h>
	#include <stdio.h>
	int main (int argc, char** argv) {
		long i;
		for (i = 0; i < 1024*1024*1024; ++i)
			printf(" ");
	}
-
Checking the required time of the programs, while redirecting the actual
output (the billion white spaces compared to nothing) to /dev/null
indicates that the approach used in this patch is faster regardless
of the optimization level of gcc.

Also this patch doesn't change output, which favors this approach over
the whitespace approach.

The only thing left to discuss, whether this patch is worth it, as it
only suppresses false positive warnings from gcc, but makes the
code slightly harder to read.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 builtin/commit.c |  2 +-
 wt-status.c      | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 65cf2a7..34bc274 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -773,7 +773,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 				committer_ident.buf);
 
 		if (ident_shown)
-			status_printf_ln(s, GIT_COLOR_NORMAL, "");
+			status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
 
 		saved_color_setting = s->use_color;
 		s->use_color = 0;
diff --git a/wt-status.c b/wt-status.c
index cb24f1f..912ed88 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -179,7 +179,7 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 	} else {
 		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
 	}
-	status_printf_ln(s, c, "");
+	status_printf_ln(s, c, "%s", "");
 }
 
 static void wt_status_print_cached_header(struct wt_status *s)
@@ -195,7 +195,7 @@ static void wt_status_print_cached_header(struct wt_status *s)
 		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
 		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
-	status_printf_ln(s, c, "");
+	status_printf_ln(s, c, "%s", "");
 }
 
 static void wt_status_print_dirty_header(struct wt_status *s,
@@ -214,7 +214,7 @@ static void wt_status_print_dirty_header(struct wt_status *s,
 	status_printf_ln(s, c, _("  (use \"git checkout -- <file>...\" to discard changes in working directory)"));
 	if (has_dirty_submodules)
 		status_printf_ln(s, c, _("  (commit or discard the untracked or modified content in submodules)"));
-	status_printf_ln(s, c, "");
+	status_printf_ln(s, c, "%s", "");
 }
 
 static void wt_status_print_other_header(struct wt_status *s,
@@ -226,12 +226,12 @@ static void wt_status_print_other_header(struct wt_status *s,
 	if (!advice_status_hints)
 		return;
 	status_printf_ln(s, c, _("  (use \"git %s <file>...\" to include in what will be committed)"), how);
-	status_printf_ln(s, c, "");
+	status_printf_ln(s, c, "%s", "");
 }
 
 static void wt_status_print_trailer(struct wt_status *s)
 {
-	status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
+	status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
 }
 
 #define quote_path quote_path_relative
@@ -1192,7 +1192,7 @@ void wt_status_print(struct wt_status *s)
 				on_what = _("Not currently on any branch.");
 			}
 		}
-		status_printf(s, color(WT_STATUS_HEADER, s), "");
+		status_printf(s, color(WT_STATUS_HEADER, s), "%s", "");
 		status_printf_more(s, branch_status_color, "%s", on_what);
 		status_printf_more(s, branch_color, "%s\n", branch_name);
 		if (!s->is_initial)
@@ -1205,9 +1205,9 @@ void wt_status_print(struct wt_status *s)
 	free(state.detached_from);
 
 	if (s->is_initial) {
-		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
+		status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
-		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
+		status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
 	}
 
 	wt_status_print_updated(s);
@@ -1224,7 +1224,7 @@ void wt_status_print(struct wt_status *s)
 		if (s->show_ignored_files)
 			wt_status_print_other(s, &s->ignored, _("Ignored files"), "add -f");
 		if (advice_status_u_option && 2000 < s->untracked_in_ms) {
-			status_printf_ln(s, GIT_COLOR_NORMAL, "");
+			status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
 			status_printf_ln(s, GIT_COLOR_NORMAL,
 					 _("It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
 					   "may speed it up, but you have to be careful not to forget to add\n"
-- 
1.8.3.3.754.g9c3c367.dirty

^ permalink raw reply related	[relevance 5%]

* Re: [PATCH] status_printf_ln: Suppress false positive warnings of empty format string.
  2013-07-19 14:08  5% [PATCH] status_printf_ln: Suppress false positive warnings of empty format string Stefan Beller
@ 2013-07-19 16:01  2% ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2013-07-19 16:01 UTC (permalink / raw)
  To: Stefan Beller; +Cc: peff, git

Stefan Beller <stefanbeller@googlemail.com> writes:

> This is a response to 8dd0ee823f1829a3aa228c3c73e31de5c89b5317.
>
> Instead of having an empty string as format for the printf like function
> status_printf_ln, we could insert an empty string into the format
> parameter.
>
> A similar fixup commit is found in linux (2e4c332913b5), but there
> the empty string is replaced by a string containing one whitespace.
>
> To determine, which approach is better I setup 2 test programs, which
> either have a whitespace format (" ") or the empty string ("%s", ""),
> looking like:
> -
> 	#include <stdlib.h>
> 	#include <stdio.h>
> 	int main (int argc, char** argv) {
> 		long i;
> 		for (i = 0; i < 1024*1024*1024; ++i)
> 			printf(" ");
> 	}
> -
> Checking the required time of the programs, while redirecting the actual
> output (the billion white spaces compared to nothing) to /dev/null
> indicates that the approach used in this patch is faster regardless
> of the optimization level of gcc.
>
> Also this patch doesn't change output, which favors this approach over
> the whitespace approach.

Even if the " " variant is faster, it does not matter if its output
is incorrect ;-)

> The only thing left to discuss, whether this patch is worth it, as it
> only suppresses false positive warnings from gcc, but makes the
> code slightly harder to read.

I think we discussed this already?  The conclusion was it is silly
for GCC to warn on -Wformat-zero-length for user-defined function in
the first place, IIRC.  func(other, args, fmt,...), when invoked as
func(other, args, ""), may very well do something useful regardless
of the formatting part based on other args.

For that matter, I personally think -Wformat-zero-length warning for
standard ones, like

	printf("");

is silly, too.  It is not like

	printf("", extra, arg);

is not caught as an error.

So we can just add -Wno-format-zero-length after -Wall and be done
with it?

>
> Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
> ---
>  builtin/commit.c |  2 +-
>  wt-status.c      | 18 +++++++++---------
>  2 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/builtin/commit.c b/builtin/commit.c
> index 65cf2a7..34bc274 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -773,7 +773,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
>  				committer_ident.buf);
>  
>  		if (ident_shown)
> -			status_printf_ln(s, GIT_COLOR_NORMAL, "");
> +			status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
>  
>  		saved_color_setting = s->use_color;
>  		s->use_color = 0;
> diff --git a/wt-status.c b/wt-status.c
> index cb24f1f..912ed88 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -179,7 +179,7 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
>  	} else {
>  		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
>  	}
> -	status_printf_ln(s, c, "");
> +	status_printf_ln(s, c, "%s", "");
>  }
>  
>  static void wt_status_print_cached_header(struct wt_status *s)
> @@ -195,7 +195,7 @@ static void wt_status_print_cached_header(struct wt_status *s)
>  		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
>  	else
>  		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
> -	status_printf_ln(s, c, "");
> +	status_printf_ln(s, c, "%s", "");
>  }
>  
>  static void wt_status_print_dirty_header(struct wt_status *s,
> @@ -214,7 +214,7 @@ static void wt_status_print_dirty_header(struct wt_status *s,
>  	status_printf_ln(s, c, _("  (use \"git checkout -- <file>...\" to discard changes in working directory)"));
>  	if (has_dirty_submodules)
>  		status_printf_ln(s, c, _("  (commit or discard the untracked or modified content in submodules)"));
> -	status_printf_ln(s, c, "");
> +	status_printf_ln(s, c, "%s", "");
>  }
>  
>  static void wt_status_print_other_header(struct wt_status *s,
> @@ -226,12 +226,12 @@ static void wt_status_print_other_header(struct wt_status *s,
>  	if (!advice_status_hints)
>  		return;
>  	status_printf_ln(s, c, _("  (use \"git %s <file>...\" to include in what will be committed)"), how);
> -	status_printf_ln(s, c, "");
> +	status_printf_ln(s, c, "%s", "");
>  }
>  
>  static void wt_status_print_trailer(struct wt_status *s)
>  {
> -	status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
> +	status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
>  }
>  
>  #define quote_path quote_path_relative
> @@ -1192,7 +1192,7 @@ void wt_status_print(struct wt_status *s)
>  				on_what = _("Not currently on any branch.");
>  			}
>  		}
> -		status_printf(s, color(WT_STATUS_HEADER, s), "");
> +		status_printf(s, color(WT_STATUS_HEADER, s), "%s", "");
>  		status_printf_more(s, branch_status_color, "%s", on_what);
>  		status_printf_more(s, branch_color, "%s\n", branch_name);
>  		if (!s->is_initial)
> @@ -1205,9 +1205,9 @@ void wt_status_print(struct wt_status *s)
>  	free(state.detached_from);
>  
>  	if (s->is_initial) {
> -		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
> +		status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
>  		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
> -		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
> +		status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
>  	}
>  
>  	wt_status_print_updated(s);
> @@ -1224,7 +1224,7 @@ void wt_status_print(struct wt_status *s)
>  		if (s->show_ignored_files)
>  			wt_status_print_other(s, &s->ignored, _("Ignored files"), "add -f");
>  		if (advice_status_u_option && 2000 < s->untracked_in_ms) {
> -			status_printf_ln(s, GIT_COLOR_NORMAL, "");
> +			status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
>  			status_printf_ln(s, GIT_COLOR_NORMAL,
>  					 _("It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
>  					   "may speed it up, but you have to be careful not to forget to add\n"

^ permalink raw reply	[relevance 2%]

* [PATCH 1/4] Replace deprecated OPT_BOOLEAN by OPT_BOOL
  @ 2013-07-29 19:49  5% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-07-29 19:49 UTC (permalink / raw)
  To: git; +Cc: Stefan Beller

This task emerged from b04ba2bb4.
All occurrences of the respective variables have been reviewed and none
of them relied on the counting up mechanism, but all of them were
using the variable as a true boolean.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 builtin/check-attr.c |  8 ++++----
 builtin/checkout.c   | 10 +++++-----
 builtin/clone.c      | 16 ++++++++--------
 builtin/fsck.c       | 16 ++++++++--------
 builtin/grep.c       | 36 ++++++++++++++++++------------------
 builtin/log.c        | 12 ++++++------
 builtin/ls-tree.c    |  6 +++---
 builtin/merge-file.c |  2 +-
 builtin/merge.c      | 12 ++++++------
 builtin/mv.c         |  2 +-
 builtin/name-rev.c   | 12 ++++++------
 builtin/notes.c      |  4 ++--
 builtin/replace.c    |  6 +++---
 builtin/reset.c      |  2 +-
 builtin/rev-parse.c  |  4 ++--
 15 files changed, 74 insertions(+), 74 deletions(-)

diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 075d01d..6e5cd88 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -16,10 +16,10 @@ NULL
 static int null_term_line;
 
 static const struct option check_attr_options[] = {
-	OPT_BOOLEAN('a', "all", &all_attrs, N_("report all attributes set on file")),
-	OPT_BOOLEAN(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
-	OPT_BOOLEAN(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
-	OPT_BOOLEAN('z', NULL, &null_term_line,
+	OPT_BOOL('a', "all", &all_attrs, N_("report all attributes set on file")),
+	OPT_BOOL(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
+	OPT_BOOL(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
+	OPT_BOOL('z', NULL, &null_term_line,
 		N_("input paths are terminated by a null character")),
 	OPT_END()
 };
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 646a475..8b48f4a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1056,8 +1056,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 			   N_("create and checkout a new branch")),
 		OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
 			   N_("create/reset and checkout a branch")),
-		OPT_BOOLEAN('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
-		OPT_BOOLEAN(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
+		OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
+		OPT_BOOL(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
 		OPT_SET_INT('t', "track",  &opts.track, N_("set upstream info for new branch"),
 			BRANCH_TRACK_EXPLICIT),
 		OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new branch"), N_("new unparented branch")),
@@ -1066,11 +1066,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT('3', "theirs", &opts.writeout_stage, N_("checkout their version for unmerged files"),
 			    3),
 		OPT__FORCE(&opts.force, N_("force checkout (throw away local modifications)")),
-		OPT_BOOLEAN('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
-		OPT_BOOLEAN(0, "overwrite-ignore", &opts.overwrite_ignore, N_("update ignored files (default)")),
+		OPT_BOOL('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
+		OPT_BOOL(0, "overwrite-ignore", &opts.overwrite_ignore, N_("update ignored files (default)")),
 		OPT_STRING(0, "conflict", &conflict_style, N_("style"),
 			   N_("conflict style (merge or diff3)")),
-		OPT_BOOLEAN('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
+		OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
 		OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree,
 			 N_("do not limit pathspecs to sparse entries only")),
 		OPT_HIDDEN_BOOL(0, "guess", &dwim_new_local_branch,
diff --git a/builtin/clone.c b/builtin/clone.c
index e7b0b13..ca3eb68 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -62,22 +62,22 @@ static struct option builtin_clone_options[] = {
 	OPT__VERBOSITY(&option_verbosity),
 	OPT_BOOL(0, "progress", &option_progress,
 		 N_("force progress reporting")),
-	OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
-		    N_("don't create a checkout")),
+	OPT_BOOL('n', "no-checkout", &option_no_checkout,
+		 N_("don't create a checkout")),
 	OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
 	OPT_HIDDEN_BOOL(0, "naked", &option_bare,
 			N_("create a bare repository")),
-	OPT_BOOLEAN(0, "mirror", &option_mirror,
-		    N_("create a mirror repository (implies bare)")),
+	OPT_BOOL(0, "mirror", &option_mirror,
+		 N_("create a mirror repository (implies bare)")),
 	OPT_BOOL('l', "local", &option_local,
 		N_("to clone from a local repository")),
-	OPT_BOOLEAN(0, "no-hardlinks", &option_no_hardlinks,
+	OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
 		    N_("don't use local hardlinks, always copy")),
-	OPT_BOOLEAN('s', "shared", &option_shared,
+	OPT_BOOL('s', "shared", &option_shared,
 		    N_("setup as shared repository")),
-	OPT_BOOLEAN(0, "recursive", &option_recursive,
+	OPT_BOOL(0, "recursive", &option_recursive,
 		    N_("initialize submodules in the clone")),
-	OPT_BOOLEAN(0, "recurse-submodules", &option_recursive,
+	OPT_BOOL(0, "recurse-submodules", &option_recursive,
 		    N_("initialize submodules in the clone")),
 	OPT_STRING(0, "template", &option_template, N_("template-directory"),
 		   N_("directory from which templates will be used")),
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 9909b6d..39fa5e8 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -611,15 +611,15 @@ static char const * const fsck_usage[] = {
 
 static struct option fsck_opts[] = {
 	OPT__VERBOSE(&verbose, N_("be verbose")),
-	OPT_BOOLEAN(0, "unreachable", &show_unreachable, N_("show unreachable objects")),
+	OPT_BOOL(0, "unreachable", &show_unreachable, N_("show unreachable objects")),
 	OPT_BOOL(0, "dangling", &show_dangling, N_("show dangling objects")),
-	OPT_BOOLEAN(0, "tags", &show_tags, N_("report tags")),
-	OPT_BOOLEAN(0, "root", &show_root, N_("report root nodes")),
-	OPT_BOOLEAN(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
-	OPT_BOOLEAN(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
-	OPT_BOOLEAN(0, "full", &check_full, N_("also consider packs and alternate objects")),
-	OPT_BOOLEAN(0, "strict", &check_strict, N_("enable more strict checking")),
-	OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
+	OPT_BOOL(0, "tags", &show_tags, N_("report tags")),
+	OPT_BOOL(0, "root", &show_root, N_("report root nodes")),
+	OPT_BOOL(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
+	OPT_BOOL(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
+	OPT_BOOL(0, "full", &check_full, N_("also consider packs and alternate objects")),
+	OPT_BOOL(0, "strict", &check_strict, N_("enable more strict checking")),
+	OPT_BOOL(0, "lost-found", &write_lost_and_found,
 				N_("write dangling objects in .git/lost-found")),
 	OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
 	OPT_END(),
diff --git a/builtin/grep.c b/builtin/grep.c
index d3b3b1d..03c2e93 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -638,20 +638,20 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	int pattern_type_arg = GREP_PATTERN_TYPE_UNSPECIFIED;
 
 	struct option options[] = {
-		OPT_BOOLEAN(0, "cached", &cached,
+		OPT_BOOL(0, "cached", &cached,
 			N_("search in index instead of in the work tree")),
 		OPT_NEGBIT(0, "no-index", &use_index,
 			 N_("find in contents not managed by git"), 1),
-		OPT_BOOLEAN(0, "untracked", &untracked,
+		OPT_BOOL(0, "untracked", &untracked,
 			N_("search in both tracked and untracked files")),
 		OPT_SET_INT(0, "exclude-standard", &opt_exclude,
 			    N_("search also in ignored files"), 1),
 		OPT_GROUP(""),
-		OPT_BOOLEAN('v', "invert-match", &opt.invert,
+		OPT_BOOL('v', "invert-match", &opt.invert,
 			N_("show non-matching lines")),
-		OPT_BOOLEAN('i', "ignore-case", &opt.ignore_case,
+		OPT_BOOL('i', "ignore-case", &opt.ignore_case,
 			N_("case insensitive matching")),
-		OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
+		OPT_BOOL('w', "word-regexp", &opt.word_regexp,
 			N_("match patterns only at word boundaries")),
 		OPT_SET_INT('a', "text", &opt.binary,
 			N_("process binary files as text"), GREP_BINARY_TEXT),
@@ -675,26 +675,26 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 			    N_("use Perl-compatible regular expressions"),
 			    GREP_PATTERN_TYPE_PCRE),
 		OPT_GROUP(""),
-		OPT_BOOLEAN('n', "line-number", &opt.linenum, N_("show line numbers")),
+		OPT_BOOL('n', "line-number", &opt.linenum, N_("show line numbers")),
 		OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show filenames"), 1),
 		OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1),
 		OPT_NEGBIT(0, "full-name", &opt.relative,
 			N_("show filenames relative to top directory"), 1),
-		OPT_BOOLEAN('l', "files-with-matches", &opt.name_only,
+		OPT_BOOL('l', "files-with-matches", &opt.name_only,
 			N_("show only filenames instead of matching lines")),
-		OPT_BOOLEAN(0, "name-only", &opt.name_only,
+		OPT_BOOL(0, "name-only", &opt.name_only,
 			N_("synonym for --files-with-matches")),
-		OPT_BOOLEAN('L', "files-without-match",
+		OPT_BOOL('L', "files-without-match",
 			&opt.unmatch_name_only,
 			N_("show only the names of files without match")),
-		OPT_BOOLEAN('z', "null", &opt.null_following_name,
+		OPT_BOOL('z', "null", &opt.null_following_name,
 			N_("print NUL after filenames")),
 		OPT_BOOLEAN('c', "count", &opt.count,
 			N_("show the number of matches instead of matching lines")),
 		OPT__COLOR(&opt.color, N_("highlight matches")),
-		OPT_BOOLEAN(0, "break", &opt.file_break,
+		OPT_BOOL(0, "break", &opt.file_break,
 			N_("print empty line between matches from different files")),
-		OPT_BOOLEAN(0, "heading", &opt.heading,
+		OPT_BOOL(0, "heading", &opt.heading,
 			N_("show filename only once above matches from same file")),
 		OPT_GROUP(""),
 		OPT_CALLBACK('C', "context", &opt, N_("n"),
@@ -706,9 +706,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 			N_("show <n> context lines after matches")),
 		OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
 			context_callback),
-		OPT_BOOLEAN('p', "show-function", &opt.funcname,
+		OPT_BOOL('p', "show-function", &opt.funcname,
 			N_("show a line with the function name before matches")),
-		OPT_BOOLEAN('W', "function-context", &opt.funcbody,
+		OPT_BOOL('W', "function-context", &opt.funcbody,
 			N_("show the surrounding function")),
 		OPT_GROUP(""),
 		OPT_CALLBACK('f', NULL, &opt, N_("file"),
@@ -718,7 +718,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 0, "and", &opt, NULL,
 		  N_("combine patterns specified with -e"),
 		  PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
-		OPT_BOOLEAN(0, "or", &dummy, ""),
+		OPT_BOOL(0, "or", &dummy, ""),
 		{ OPTION_CALLBACK, 0, "not", &opt, NULL, "",
 		  PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
 		{ OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
@@ -729,7 +729,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		  close_callback },
 		OPT__QUIET(&opt.status_only,
 			   N_("indicate hit with exit status without output")),
-		OPT_BOOLEAN(0, "all-match", &opt.all_match,
+		OPT_BOOL(0, "all-match", &opt.all_match,
 			N_("show only matches from files that match all patterns")),
 		{ OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
 		  N_("show parse tree for grep expression"),
@@ -738,8 +738,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		{ OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
 			N_("pager"), N_("show matching files in the pager"),
 			PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
-		OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed__ignored,
-			    N_("allow calling of grep(1) (ignored by this build)")),
+		OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored,
+			 N_("allow calling of grep(1) (ignored by this build)")),
 		{ OPTION_CALLBACK, 0, "help-all", &options, NULL, N_("show usage"),
 		  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
 		OPT_END()
diff --git a/builtin/log.c b/builtin/log.c
index 05e374d..9b6c910 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1179,10 +1179,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
 			    N_("don't strip/add [PATCH]"),
 			    PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
-		OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
-			    N_("don't output binary diffs")),
-		OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
-			    N_("don't include a patch matching a commit upstream")),
+		OPT_BOOL(0, "no-binary", &no_binary_diff,
+			 N_("don't output binary diffs")),
+		OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
+			 N_("don't include a patch matching a commit upstream")),
 		{ OPTION_SET_INT, 'p', "no-stat", &use_patch_format, NULL,
 		  N_("show patch format instead of default (patch + stat)"),
 		  PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1},
@@ -1210,8 +1210,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 			    PARSE_OPT_OPTARG, thread_callback },
 		OPT_STRING(0, "signature", &signature, N_("signature"),
 			    N_("add a signature")),
-		OPT_BOOLEAN(0, "quiet", &quiet,
-			    N_("don't print the patch filenames")),
+		OPT_BOOL(0, "quiet", &quiet,
+			 N_("don't print the patch filenames")),
 		OPT_END()
 	};
 
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index fb76e38..de88563 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -138,9 +138,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 			LS_NAME_ONLY),
 		OPT_SET_INT(0, "full-name", &chomp_prefix,
 			    N_("use full path names"), 0),
-		OPT_BOOLEAN(0, "full-tree", &full_tree,
-			    N_("list entire tree; not just current directory "
-			       "(implies --full-name)")),
+		OPT_BOOL(0, "full-tree", &full_tree,
+			 N_("list entire tree; not just current directory "
+			    "(implies --full-name)")),
 		OPT__ABBREV(&abbrev),
 		OPT_END()
 	};
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index c0570f2..844f84f 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -30,7 +30,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 	int quiet = 0;
 	int prefixlen = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('p', "stdout", &to_stdout, N_("send results to standard output")),
+		OPT_BOOL('p', "stdout", &to_stdout, N_("send results to standard output")),
 		OPT_SET_INT(0, "diff3", &xmp.style, N_("use a diff3 based merge"), XDL_MERGE_DIFF3),
 		OPT_SET_INT(0, "ours", &xmp.favor, N_("for conflicts, use our version"),
 			    XDL_MERGE_FAVOR_OURS),
diff --git a/builtin/merge.c b/builtin/merge.c
index 34a6166..a8cf4a2 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -197,15 +197,15 @@ static struct option builtin_merge_options[] = {
 	{ OPTION_CALLBACK, 'n', NULL, NULL, NULL,
 		N_("do not show a diffstat at the end of the merge"),
 		PARSE_OPT_NOARG, option_parse_n },
-	OPT_BOOLEAN(0, "stat", &show_diffstat,
+	OPT_BOOL(0, "stat", &show_diffstat,
 		N_("show a diffstat at the end of the merge")),
-	OPT_BOOLEAN(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
+	OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
 	{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
 	  N_("add (at most <n>) entries from shortlog to merge commit message"),
 	  PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
-	OPT_BOOLEAN(0, "squash", &squash,
+	OPT_BOOL(0, "squash", &squash,
 		N_("create a single commit instead of doing a merge")),
-	OPT_BOOLEAN(0, "commit", &option_commit,
+	OPT_BOOL(0, "commit", &option_commit,
 		N_("perform a commit if the merge succeeds (default)")),
 	OPT_BOOL('e', "edit", &option_edit,
 		N_("edit message before committing")),
@@ -224,12 +224,12 @@ static struct option builtin_merge_options[] = {
 		N_("merge commit message (for a non-fast-forward merge)"),
 		option_parse_message),
 	OPT__VERBOSITY(&verbosity),
-	OPT_BOOLEAN(0, "abort", &abort_current_merge,
+	OPT_BOOL(0, "abort", &abort_current_merge,
 		N_("abort the current in-progress merge")),
 	OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
 	{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
 	  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-	OPT_BOOLEAN(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
+	OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
 	OPT_END()
 };
 
diff --git a/builtin/mv.c b/builtin/mv.c
index 034fec9..be6fa77 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -62,7 +62,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 		OPT__VERBOSE(&verbose, N_("be verbose")),
 		OPT__DRY_RUN(&show_only, N_("dry run")),
 		OPT__FORCE(&force, N_("force move/rename even if target exists")),
-		OPT_BOOLEAN('k', NULL, &ignore_errors, N_("skip move/rename errors")),
+		OPT_BOOL('k', NULL, &ignore_errors, N_("skip move/rename errors")),
 		OPT_END(),
 	};
 	const char **source, **destination, **dest_path;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 0aaa19e..a908a34 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -310,15 +310,15 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 	int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
 	struct name_ref_data data = { 0, 0, NULL };
 	struct option opts[] = {
-		OPT_BOOLEAN(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
-		OPT_BOOLEAN(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
+		OPT_BOOL(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
+		OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
 		OPT_STRING(0, "refs", &data.ref_filter, N_("pattern"),
 				   N_("only use refs matching <pattern>")),
 		OPT_GROUP(""),
-		OPT_BOOLEAN(0, "all", &all, N_("list all commits reachable from all refs")),
-		OPT_BOOLEAN(0, "stdin", &transform_stdin, N_("read from stdin")),
-		OPT_BOOLEAN(0, "undefined", &allow_undefined, N_("allow to print `undefined` names")),
-		OPT_BOOLEAN(0, "always",     &always,
+		OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
+		OPT_BOOL(0, "stdin", &transform_stdin, N_("read from stdin")),
+		OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
+		OPT_BOOL(0, "always",     &always,
 			   N_("show abbreviated commit object as fallback")),
 		{
 			/* A Hidden OPT_BOOL */
diff --git a/builtin/notes.c b/builtin/notes.c
index 8f63cb2..d459e23 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -483,7 +483,7 @@ static int copy(int argc, const char **argv, const char *prefix)
 	const char *rewrite_cmd = NULL;
 	struct option options[] = {
 		OPT__FORCE(&force, N_("replace existing notes")),
-		OPT_BOOLEAN(0, "stdin", &from_stdin, N_("read objects from stdin")),
+		OPT_BOOL(0, "stdin", &from_stdin, N_("read objects from stdin")),
 		OPT_STRING(0, "for-rewrite", &rewrite_cmd, N_("command"),
 			   N_("load rewriting config for <command> (implies "
 			      "--stdin)")),
@@ -853,7 +853,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
 		OPT_BIT(0, "ignore-missing", &flag,
 			N_("attempt to remove non-existent note is not an error"),
 			IGNORE_MISSING),
-		OPT_BOOLEAN(0, "stdin", &from_stdin,
+		OPT_BOOL(0, "stdin", &from_stdin,
 			    N_("read object names from the standard input")),
 		OPT_END()
 	};
diff --git a/builtin/replace.c b/builtin/replace.c
index 59d3115..11b0a55 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -118,9 +118,9 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
 {
 	int list = 0, delete = 0, force = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('l', NULL, &list, N_("list replace refs")),
-		OPT_BOOLEAN('d', NULL, &delete, N_("delete replace refs")),
-		OPT_BOOLEAN('f', NULL, &force, N_("replace the ref if it exists")),
+		OPT_BOOL('l', NULL, &list, N_("list replace refs")),
+		OPT_BOOL('d', NULL, &delete, N_("delete replace refs")),
+		OPT_BOOL('f', NULL, &force, N_("replace the ref if it exists")),
 		OPT_END()
 	};
 
diff --git a/builtin/reset.c b/builtin/reset.c
index afa6e02..0905815 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -258,7 +258,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				N_("reset HEAD, index and working tree"), MERGE),
 		OPT_SET_INT(0, "keep", &reset_type,
 				N_("reset HEAD but keep local changes"), KEEP),
-		OPT_BOOLEAN('p', "patch", &patch_mode, N_("select hunks interactively")),
+		OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
 		OPT_END()
 	};
 
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index de894c7..67e8ccf 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -346,9 +346,9 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 		NULL
 	};
 	static struct option parseopt_opts[] = {
-		OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
+		OPT_BOOL(0, "keep-dashdash", &keep_dashdash,
 					N_("keep the `--` passed as an arg")),
-		OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option,
+		OPT_BOOL(0, "stop-at-non-option", &stop_at_non_option,
 					N_("stop parsing after the "
 					   "first non-option argument")),
 		OPT_END(),
-- 
1.8.4.rc0.1.g8f6a3e5

^ permalink raw reply related	[relevance 5%]

* [PATCHv2 2/9] Replace deprecated OPT_BOOLEAN by OPT_BOOL
  @ 2013-07-31 16:28  3% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-07-31 16:28 UTC (permalink / raw)
  To: git; +Cc: Stefan Beller

This task emerged from b04ba2bb (parse-options: deprecate OPT_BOOLEAN,
2011-09-27). All occurrences of the respective variables have
been reviewed and none of them relied on the counting up mechanism,
but all of them were using the variable as a true boolean.

This patch does not change semantics of any command intentionally.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 builtin/apply.c          | 24 ++++++++++++------------
 builtin/bisect--helper.c |  8 ++++----
 builtin/blame.c          |  8 ++++----
 builtin/branch.c         | 10 +++++-----
 builtin/check-attr.c     |  8 ++++----
 builtin/check-ignore.c   | 12 ++++++------
 builtin/checkout-index.c |  6 +++---
 builtin/checkout.c       | 10 +++++-----
 builtin/clean.c          |  6 +++---
 builtin/clone.c          | 16 ++++++++--------
 builtin/commit.c         | 36 ++++++++++++++++++------------------
 builtin/config.c         |  2 +-
 builtin/describe.c       | 20 ++++++++++----------
 builtin/fast-export.c    | 10 +++++-----
 builtin/fetch.c          | 24 ++++++++++++------------
 builtin/fsck.c           | 16 ++++++++--------
 builtin/gc.c             |  4 ++--
 builtin/grep.c           | 38 +++++++++++++++++++-------------------
 builtin/hash-object.c    |  6 +++---
 builtin/log.c            |  8 ++++----
 builtin/ls-files.c       | 24 ++++++++++++------------
 builtin/ls-tree.c        |  6 +++---
 builtin/merge-base.c     | 10 +++++-----
 builtin/merge-file.c     |  2 +-
 builtin/merge.c          | 12 ++++++------
 builtin/mv.c             |  2 +-
 builtin/name-rev.c       | 12 ++++++------
 builtin/notes.c          |  4 ++--
 builtin/push.c           |  6 +++---
 builtin/remote.c         | 28 ++++++++++++++--------------
 builtin/replace.c        |  6 +++---
 builtin/reset.c          |  2 +-
 builtin/rev-parse.c      |  4 ++--
 builtin/rm.c             |  6 +++---
 builtin/shortlog.c       | 12 ++++++------
 builtin/show-branch.c    | 28 ++++++++++++++--------------
 builtin/show-ref.c       | 10 +++++-----
 builtin/tag.c            |  4 ++--
 builtin/update-ref.c     |  4 ++--
 39 files changed, 227 insertions(+), 227 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 50912c9..ef32e4f 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -4363,23 +4363,23 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 		{ OPTION_CALLBACK, 'p', NULL, NULL, N_("num"),
 			N_("remove <num> leading slashes from traditional diff paths"),
 			0, option_parse_p },
-		OPT_BOOLEAN(0, "no-add", &no_add,
+		OPT_BOOL(0, "no-add", &no_add,
 			N_("ignore additions made by the patch")),
-		OPT_BOOLEAN(0, "stat", &diffstat,
+		OPT_BOOL(0, "stat", &diffstat,
 			N_("instead of applying the patch, output diffstat for the input")),
 		OPT_NOOP_NOARG(0, "allow-binary-replacement"),
 		OPT_NOOP_NOARG(0, "binary"),
-		OPT_BOOLEAN(0, "numstat", &numstat,
+		OPT_BOOL(0, "numstat", &numstat,
 			N_("show number of added and deleted lines in decimal notation")),
-		OPT_BOOLEAN(0, "summary", &summary,
+		OPT_BOOL(0, "summary", &summary,
 			N_("instead of applying the patch, output a summary for the input")),
-		OPT_BOOLEAN(0, "check", &check,
+		OPT_BOOL(0, "check", &check,
 			N_("instead of applying the patch, see if the patch is applicable")),
-		OPT_BOOLEAN(0, "index", &check_index,
+		OPT_BOOL(0, "index", &check_index,
 			N_("make sure the patch is applicable to the current index")),
-		OPT_BOOLEAN(0, "cached", &cached,
+		OPT_BOOL(0, "cached", &cached,
 			N_("apply a patch without touching the working tree")),
-		OPT_BOOLEAN(0, "apply", &force_apply,
+		OPT_BOOL(0, "apply", &force_apply,
 			N_("also apply the patch (use with --stat/--summary/--check)")),
 		OPT_BOOL('3', "3way", &threeway,
 			 N_( "attempt three-way merge if a patch does not apply")),
@@ -4399,13 +4399,13 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 		{ OPTION_CALLBACK, 0, "ignore-whitespace", NULL, NULL,
 			N_("ignore changes in whitespace when finding context"),
 			PARSE_OPT_NOARG, option_parse_space_change },
-		OPT_BOOLEAN('R', "reverse", &apply_in_reverse,
+		OPT_BOOL('R', "reverse", &apply_in_reverse,
 			N_("apply the patch in reverse")),
-		OPT_BOOLEAN(0, "unidiff-zero", &unidiff_zero,
+		OPT_BOOL(0, "unidiff-zero", &unidiff_zero,
 			N_("don't expect at least one line of context")),
-		OPT_BOOLEAN(0, "reject", &apply_with_reject,
+		OPT_BOOL(0, "reject", &apply_with_reject,
 			N_("leave the rejected hunks in corresponding *.rej files")),
-		OPT_BOOLEAN(0, "allow-overlap", &allow_overlap,
+		OPT_BOOL(0, "allow-overlap", &allow_overlap,
 			N_("allow overlapping hunks")),
 		OPT__VERBOSE(&apply_verbosely, N_("be verbose")),
 		OPT_BIT(0, "inaccurate-eof", &options,
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index e3884e3..3324229 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -13,10 +13,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 	int next_all = 0;
 	int no_checkout = 0;
 	struct option options[] = {
-		OPT_BOOLEAN(0, "next-all", &next_all,
-			    N_("perform 'git bisect next'")),
-		OPT_BOOLEAN(0, "no-checkout", &no_checkout,
-			    N_("update BISECT_HEAD instead of checking out the current commit")),
+		OPT_BOOL(0, "next-all", &next_all,
+			 N_("perform 'git bisect next'")),
+		OPT_BOOL(0, "no-checkout", &no_checkout,
+			 N_("update BISECT_HEAD instead of checking out the current commit")),
 		OPT_END()
 	};
 
diff --git a/builtin/blame.c b/builtin/blame.c
index 079dcd3..f932112 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2273,10 +2273,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	static const char *revs_file = NULL;
 	static const char *contents_from = NULL;
 	static const struct option options[] = {
-		OPT_BOOLEAN(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
-		OPT_BOOLEAN('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
-		OPT_BOOLEAN(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
-		OPT_BOOLEAN(0, "show-stats", &show_stats, N_("Show work cost statistics")),
+		OPT_BOOL(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
+		OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
+		OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
+		OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")),
 		OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE),
 		OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME),
 		OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER),
diff --git a/builtin/branch.c b/builtin/branch.c
index 0836890..4daed0b 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -797,7 +797,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT( 0, "set-upstream",  &track, N_("change upstream info"),
 			BRANCH_TRACK_OVERRIDE),
 		OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"),
-		OPT_BOOLEAN(0, "unset-upstream", &unset_upstream, "Unset the upstream info"),
+		OPT_BOOL(0, "unset-upstream", &unset_upstream, "Unset the upstream info"),
 		OPT__COLOR(&branch_use_color, N_("use colored output")),
 		OPT_SET_INT('r', "remotes",     &kinds, N_("act on remote-tracking branches"),
 			REF_REMOTE_BRANCH),
@@ -822,10 +822,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
 		OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
 		OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
-		OPT_BOOLEAN(0, "list", &list, N_("list branch names")),
-		OPT_BOOLEAN('l', "create-reflog", &reflog, N_("create the branch's reflog")),
-		OPT_BOOLEAN(0, "edit-description", &edit_description,
-			    N_("edit the description for the branch")),
+		OPT_BOOL(0, "list", &list, N_("list branch names")),
+		OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
+		OPT_BOOL(0, "edit-description", &edit_description,
+			 N_("edit the description for the branch")),
 		OPT__FORCE(&force_create, N_("force creation (when already exists)")),
 		{
 			OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 075d01d..6e5cd88 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -16,10 +16,10 @@ NULL
 static int null_term_line;
 
 static const struct option check_attr_options[] = {
-	OPT_BOOLEAN('a', "all", &all_attrs, N_("report all attributes set on file")),
-	OPT_BOOLEAN(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
-	OPT_BOOLEAN(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
-	OPT_BOOLEAN('z', NULL, &null_term_line,
+	OPT_BOOL('a', "all", &all_attrs, N_("report all attributes set on file")),
+	OPT_BOOL(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
+	OPT_BOOL(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
+	OPT_BOOL('z', NULL, &null_term_line,
 		N_("input paths are terminated by a null character")),
 	OPT_END()
 };
diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c
index 4a8fc70..c9f0c9b 100644
--- a/builtin/check-ignore.c
+++ b/builtin/check-ignore.c
@@ -18,12 +18,12 @@ static const struct option check_ignore_options[] = {
 	OPT__QUIET(&quiet, N_("suppress progress reporting")),
 	OPT__VERBOSE(&verbose, N_("be verbose")),
 	OPT_GROUP(""),
-	OPT_BOOLEAN(0, "stdin", &stdin_paths,
-		    N_("read file names from stdin")),
-	OPT_BOOLEAN('z', NULL, &null_term_line,
-		    N_("input paths are terminated by a null character")),
-	OPT_BOOLEAN('n', "non-matching", &show_non_matching,
-		    N_("show non-matching input paths")),
+	OPT_BOOL(0, "stdin", &stdin_paths,
+		 N_("read file names from stdin")),
+	OPT_BOOL('z', NULL, &null_term_line,
+		 N_("input paths are terminated by a null character")),
+	OPT_BOOL('n', "non-matching", &show_non_matching,
+		 N_("show non-matching input paths")),
 	OPT_END()
 };
 
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index b1feda7..aa922ed 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -183,7 +183,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 	int prefix_length;
 	int force = 0, quiet = 0, not_new = 0;
 	struct option builtin_checkout_index_options[] = {
-		OPT_BOOLEAN('a', "all", &all,
+		OPT_BOOL('a', "all", &all,
 			N_("check out all files in the index")),
 		OPT__FORCE(&force, N_("force overwrite of existing files")),
 		OPT__QUIET(&quiet,
@@ -196,9 +196,9 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
 			N_("paths are separated with NUL character"),
 			PARSE_OPT_NOARG, option_parse_z },
-		OPT_BOOLEAN(0, "stdin", &read_from_stdin,
+		OPT_BOOL(0, "stdin", &read_from_stdin,
 			N_("read list of paths from the standard input")),
-		OPT_BOOLEAN(0, "temp", &to_tempfile,
+		OPT_BOOL(0, "temp", &to_tempfile,
 			N_("write the content to temporary files")),
 		OPT_CALLBACK(0, "prefix", NULL, N_("string"),
 			N_("when creating files, prepend <string>"),
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 646a475..8b48f4a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1056,8 +1056,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 			   N_("create and checkout a new branch")),
 		OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
 			   N_("create/reset and checkout a branch")),
-		OPT_BOOLEAN('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
-		OPT_BOOLEAN(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
+		OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
+		OPT_BOOL(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
 		OPT_SET_INT('t', "track",  &opts.track, N_("set upstream info for new branch"),
 			BRANCH_TRACK_EXPLICIT),
 		OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new branch"), N_("new unparented branch")),
@@ -1066,11 +1066,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT('3', "theirs", &opts.writeout_stage, N_("checkout their version for unmerged files"),
 			    3),
 		OPT__FORCE(&opts.force, N_("force checkout (throw away local modifications)")),
-		OPT_BOOLEAN('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
-		OPT_BOOLEAN(0, "overwrite-ignore", &opts.overwrite_ignore, N_("update ignored files (default)")),
+		OPT_BOOL('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
+		OPT_BOOL(0, "overwrite-ignore", &opts.overwrite_ignore, N_("update ignored files (default)")),
 		OPT_STRING(0, "conflict", &conflict_style, N_("style"),
 			   N_("conflict style (merge or diff3)")),
-		OPT_BOOLEAN('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
+		OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
 		OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree,
 			 N_("do not limit pathspecs to sparse entries only")),
 		OPT_HIDDEN_BOOL(0, "guess", &dwim_new_local_branch,
diff --git a/builtin/clean.c b/builtin/clean.c
index dba8387..df0f61e 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -851,12 +851,12 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 		OPT__DRY_RUN(&dry_run, N_("dry run")),
 		OPT__FORCE(&force, N_("force")),
 		OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")),
-		OPT_BOOLEAN('d', NULL, &remove_directories,
+		OPT_BOOL('d', NULL, &remove_directories,
 				N_("remove whole directories")),
 		{ OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"),
 		  N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb },
-		OPT_BOOLEAN('x', NULL, &ignored, N_("remove ignored files, too")),
-		OPT_BOOLEAN('X', NULL, &ignored_only,
+		OPT_BOOL('x', NULL, &ignored, N_("remove ignored files, too")),
+		OPT_BOOL('X', NULL, &ignored_only,
 				N_("remove only ignored files")),
 		OPT_END()
 	};
diff --git a/builtin/clone.c b/builtin/clone.c
index e7b0b13..ca3eb68 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -62,22 +62,22 @@ static struct option builtin_clone_options[] = {
 	OPT__VERBOSITY(&option_verbosity),
 	OPT_BOOL(0, "progress", &option_progress,
 		 N_("force progress reporting")),
-	OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
-		    N_("don't create a checkout")),
+	OPT_BOOL('n', "no-checkout", &option_no_checkout,
+		 N_("don't create a checkout")),
 	OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
 	OPT_HIDDEN_BOOL(0, "naked", &option_bare,
 			N_("create a bare repository")),
-	OPT_BOOLEAN(0, "mirror", &option_mirror,
-		    N_("create a mirror repository (implies bare)")),
+	OPT_BOOL(0, "mirror", &option_mirror,
+		 N_("create a mirror repository (implies bare)")),
 	OPT_BOOL('l', "local", &option_local,
 		N_("to clone from a local repository")),
-	OPT_BOOLEAN(0, "no-hardlinks", &option_no_hardlinks,
+	OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
 		    N_("don't use local hardlinks, always copy")),
-	OPT_BOOLEAN('s', "shared", &option_shared,
+	OPT_BOOL('s', "shared", &option_shared,
 		    N_("setup as shared repository")),
-	OPT_BOOLEAN(0, "recursive", &option_recursive,
+	OPT_BOOL(0, "recursive", &option_recursive,
 		    N_("initialize submodules in the clone")),
-	OPT_BOOLEAN(0, "recurse-submodules", &option_recursive,
+	OPT_BOOL(0, "recurse-submodules", &option_recursive,
 		    N_("initialize submodules in the clone")),
 	OPT_STRING(0, "template", &option_template, N_("template-directory"),
 		   N_("directory from which templates will be used")),
diff --git a/builtin/commit.c b/builtin/commit.c
index b64a083..c20426b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1209,14 +1209,14 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT(0, "long", &status_format,
 			    N_("show status in long format (default)"),
 			    STATUS_FORMAT_LONG),
-		OPT_BOOLEAN('z', "null", &s.null_termination,
-			    N_("terminate entries with NUL")),
+		OPT_BOOL('z', "null", &s.null_termination,
+			 N_("terminate entries with NUL")),
 		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
 		  N_("mode"),
 		  N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
 		  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
-		OPT_BOOLEAN(0, "ignored", &show_ignored_in_status,
-			    N_("show ignored files")),
+		OPT_BOOL(0, "ignored", &show_ignored_in_status,
+			 N_("show ignored files")),
 		{ OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
 		  N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
 		  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@ -1415,24 +1415,24 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_STRING('C', "reuse-message", &use_message, N_("commit"), N_("reuse message from specified commit")),
 		OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
 		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
-		OPT_BOOLEAN(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
-		OPT_BOOLEAN('s', "signoff", &signoff, N_("add Signed-off-by:")),
+		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
+		OPT_BOOL('s', "signoff", &signoff, N_("add Signed-off-by:")),
 		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
 		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
 		OPT_STRING(0, "cleanup", &cleanup_arg, N_("default"), N_("how to strip spaces and #comments from message")),
-		OPT_BOOLEAN(0, "status", &include_status, N_("include status in commit message template")),
+		OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")),
 		{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
 		  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 		/* end commit message options */
 
 		OPT_GROUP(N_("Commit contents options")),
-		OPT_BOOLEAN('a', "all", &all, N_("commit all changed files")),
-		OPT_BOOLEAN('i', "include", &also, N_("add specified files to index for commit")),
-		OPT_BOOLEAN(0, "interactive", &interactive, N_("interactively add files")),
-		OPT_BOOLEAN('p', "patch", &patch_interactive, N_("interactively add changes")),
-		OPT_BOOLEAN('o', "only", &only, N_("commit only specified files")),
-		OPT_BOOLEAN('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
-		OPT_BOOLEAN(0, "dry-run", &dry_run, N_("show what would be committed")),
+		OPT_BOOL('a', "all", &all, N_("commit all changed files")),
+		OPT_BOOL('i', "include", &also, N_("add specified files to index for commit")),
+		OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
+		OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
+		OPT_BOOL('o', "only", &only, N_("commit only specified files")),
+		OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
+		OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
 		OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
 			    STATUS_FORMAT_SHORT),
 		OPT_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
@@ -1441,10 +1441,10 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT(0, "long", &status_format,
 			    N_("show status in long format (default)"),
 			    STATUS_FORMAT_LONG),
-		OPT_BOOLEAN('z', "null", &s.null_termination,
-			    N_("terminate entries with NUL")),
-		OPT_BOOLEAN(0, "amend", &amend, N_("amend previous commit")),
-		OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
+		OPT_BOOL('z', "null", &s.null_termination,
+			 N_("terminate entries with NUL")),
+		OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
+		OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
 		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
 		/* end commit contents options */
 
diff --git a/builtin/config.c b/builtin/config.c
index 4010c43..da12fdb 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -75,7 +75,7 @@ static struct option builtin_config_options[] = {
 	OPT_BIT(0, "bool-or-int", &types, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
 	OPT_BIT(0, "path", &types, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOLEAN('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")),
 	OPT_END(),
 };
diff --git a/builtin/describe.c b/builtin/describe.c
index 7d73722..c94e5c3 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -406,12 +406,12 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 {
 	int contains = 0;
 	struct option options[] = {
-		OPT_BOOLEAN(0, "contains",   &contains, N_("find the tag that comes after the commit")),
-		OPT_BOOLEAN(0, "debug",      &debug, N_("debug search strategy on stderr")),
-		OPT_BOOLEAN(0, "all",        &all, N_("use any ref")),
-		OPT_BOOLEAN(0, "tags",       &tags, N_("use any tag, even unannotated")),
-		OPT_BOOLEAN(0, "long",       &longformat, N_("always use long format")),
-		OPT_BOOLEAN(0, "first-parent", &first_parent, N_("only follow first parent")),
+		OPT_BOOL(0, "contains",   &contains, N_("find the tag that comes after the commit")),
+		OPT_BOOL(0, "debug",      &debug, N_("debug search strategy on stderr")),
+		OPT_BOOL(0, "all",        &all, N_("use any ref")),
+		OPT_BOOL(0, "tags",       &tags, N_("use any tag, even unannotated")),
+		OPT_BOOL(0, "long",       &longformat, N_("always use long format")),
+		OPT_BOOL(0, "first-parent", &first_parent, N_("only follow first parent")),
 		OPT__ABBREV(&abbrev),
 		OPT_SET_INT(0, "exact-match", &max_candidates,
 			    N_("only output exact matches"), 0),
@@ -419,11 +419,11 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 			    N_("consider <n> most recent tags (default: 10)")),
 		OPT_STRING(0, "match",       &pattern, N_("pattern"),
 			   N_("only consider tags matching <pattern>")),
-		OPT_BOOLEAN(0, "always",     &always,
-			   N_("show abbreviated commit object as fallback")),
+		OPT_BOOL(0, "always",        &always,
+			N_("show abbreviated commit object as fallback")),
 		{OPTION_STRING, 0, "dirty",  &dirty, N_("mark"),
-			   N_("append <mark> on dirty working tree (default: \"-dirty\")"),
-		 PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
+			N_("append <mark> on dirty working tree (default: \"-dirty\")"),
+			PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
 		OPT_END(),
 	};
 
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index d1d68e9..32b0c3f 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -674,11 +674,11 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 			     N_("Dump marks to this file")),
 		OPT_STRING(0, "import-marks", &import_filename, N_("file"),
 			     N_("Import marks from this file")),
-		OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
-			     N_("Fake a tagger when tags lack one")),
-		OPT_BOOLEAN(0, "full-tree", &full_tree,
-			     N_("Output full tree for each commit")),
-		OPT_BOOLEAN(0, "use-done-feature", &use_done_feature,
+		OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
+			 N_("Fake a tagger when tags lack one")),
+		OPT_BOOL(0, "full-tree", &full_tree,
+			 N_("Output full tree for each commit")),
+		OPT_BOOL(0, "use-done-feature", &use_done_feature,
 			     N_("Use the done feature to terminate the stream")),
 		OPT_BOOL(0, "no-data", &no_data, N_("Skip output of blob data")),
 		OPT_END()
diff --git a/builtin/fetch.c b/builtin/fetch.c
index d784b2e..99afed0 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -56,28 +56,28 @@ static int option_parse_recurse_submodules(const struct option *opt,
 
 static struct option builtin_fetch_options[] = {
 	OPT__VERBOSITY(&verbosity),
-	OPT_BOOLEAN(0, "all", &all,
-		    N_("fetch from all remotes")),
-	OPT_BOOLEAN('a', "append", &append,
-		    N_("append to .git/FETCH_HEAD instead of overwriting")),
+	OPT_BOOL(0, "all", &all,
+		 N_("fetch from all remotes")),
+	OPT_BOOL('a', "append", &append,
+		 N_("append to .git/FETCH_HEAD instead of overwriting")),
 	OPT_STRING(0, "upload-pack", &upload_pack, N_("path"),
 		   N_("path to upload pack on remote end")),
 	OPT__FORCE(&force, N_("force overwrite of local branch")),
-	OPT_BOOLEAN('m', "multiple", &multiple,
-		    N_("fetch from multiple remotes")),
+	OPT_BOOL('m', "multiple", &multiple,
+		 N_("fetch from multiple remotes")),
 	OPT_SET_INT('t', "tags", &tags,
 		    N_("fetch all tags and associated objects"), TAGS_SET),
 	OPT_SET_INT('n', NULL, &tags,
 		    N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
-	OPT_BOOLEAN('p', "prune", &prune,
-		    N_("prune remote-tracking branches no longer on remote")),
+	OPT_BOOL('p', "prune", &prune,
+		 N_("prune remote-tracking branches no longer on remote")),
 	{ OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
 		    N_("control recursive fetching of submodules"),
 		    PARSE_OPT_OPTARG, option_parse_recurse_submodules },
-	OPT_BOOLEAN(0, "dry-run", &dry_run,
-		    N_("dry run")),
-	OPT_BOOLEAN('k', "keep", &keep, N_("keep downloaded pack")),
-	OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
+	OPT_BOOL(0, "dry-run", &dry_run,
+		 N_("dry run")),
+	OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
+	OPT_BOOL('u', "update-head-ok", &update_head_ok,
 		    N_("allow updating of HEAD ref")),
 	OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
 	OPT_STRING(0, "depth", &depth, N_("depth"),
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 9909b6d..39fa5e8 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -611,15 +611,15 @@ static char const * const fsck_usage[] = {
 
 static struct option fsck_opts[] = {
 	OPT__VERBOSE(&verbose, N_("be verbose")),
-	OPT_BOOLEAN(0, "unreachable", &show_unreachable, N_("show unreachable objects")),
+	OPT_BOOL(0, "unreachable", &show_unreachable, N_("show unreachable objects")),
 	OPT_BOOL(0, "dangling", &show_dangling, N_("show dangling objects")),
-	OPT_BOOLEAN(0, "tags", &show_tags, N_("report tags")),
-	OPT_BOOLEAN(0, "root", &show_root, N_("report root nodes")),
-	OPT_BOOLEAN(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
-	OPT_BOOLEAN(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
-	OPT_BOOLEAN(0, "full", &check_full, N_("also consider packs and alternate objects")),
-	OPT_BOOLEAN(0, "strict", &check_strict, N_("enable more strict checking")),
-	OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
+	OPT_BOOL(0, "tags", &show_tags, N_("report tags")),
+	OPT_BOOL(0, "root", &show_root, N_("report root nodes")),
+	OPT_BOOL(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
+	OPT_BOOL(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
+	OPT_BOOL(0, "full", &check_full, N_("also consider packs and alternate objects")),
+	OPT_BOOL(0, "strict", &check_strict, N_("enable more strict checking")),
+	OPT_BOOL(0, "lost-found", &write_lost_and_found,
 				N_("write dangling objects in .git/lost-found")),
 	OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
 	OPT_END(),
diff --git a/builtin/gc.c b/builtin/gc.c
index 6be6c8d..c4f7390 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -178,8 +178,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 		{ OPTION_STRING, 0, "prune", &prune_expire, N_("date"),
 			N_("prune unreferenced objects"),
 			PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
-		OPT_BOOLEAN(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
-		OPT_BOOLEAN(0, "auto", &auto_gc, N_("enable auto-gc mode")),
+		OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
+		OPT_BOOL(0, "auto", &auto_gc, N_("enable auto-gc mode")),
 		OPT_END()
 	};
 
diff --git a/builtin/grep.c b/builtin/grep.c
index d3b3b1d..7877e77 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -638,20 +638,20 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	int pattern_type_arg = GREP_PATTERN_TYPE_UNSPECIFIED;
 
 	struct option options[] = {
-		OPT_BOOLEAN(0, "cached", &cached,
+		OPT_BOOL(0, "cached", &cached,
 			N_("search in index instead of in the work tree")),
 		OPT_NEGBIT(0, "no-index", &use_index,
 			 N_("find in contents not managed by git"), 1),
-		OPT_BOOLEAN(0, "untracked", &untracked,
+		OPT_BOOL(0, "untracked", &untracked,
 			N_("search in both tracked and untracked files")),
 		OPT_SET_INT(0, "exclude-standard", &opt_exclude,
 			    N_("search also in ignored files"), 1),
 		OPT_GROUP(""),
-		OPT_BOOLEAN('v', "invert-match", &opt.invert,
+		OPT_BOOL('v', "invert-match", &opt.invert,
 			N_("show non-matching lines")),
-		OPT_BOOLEAN('i', "ignore-case", &opt.ignore_case,
+		OPT_BOOL('i', "ignore-case", &opt.ignore_case,
 			N_("case insensitive matching")),
-		OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
+		OPT_BOOL('w', "word-regexp", &opt.word_regexp,
 			N_("match patterns only at word boundaries")),
 		OPT_SET_INT('a', "text", &opt.binary,
 			N_("process binary files as text"), GREP_BINARY_TEXT),
@@ -675,26 +675,26 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 			    N_("use Perl-compatible regular expressions"),
 			    GREP_PATTERN_TYPE_PCRE),
 		OPT_GROUP(""),
-		OPT_BOOLEAN('n', "line-number", &opt.linenum, N_("show line numbers")),
+		OPT_BOOL('n', "line-number", &opt.linenum, N_("show line numbers")),
 		OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show filenames"), 1),
 		OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1),
 		OPT_NEGBIT(0, "full-name", &opt.relative,
 			N_("show filenames relative to top directory"), 1),
-		OPT_BOOLEAN('l', "files-with-matches", &opt.name_only,
+		OPT_BOOL('l', "files-with-matches", &opt.name_only,
 			N_("show only filenames instead of matching lines")),
-		OPT_BOOLEAN(0, "name-only", &opt.name_only,
+		OPT_BOOL(0, "name-only", &opt.name_only,
 			N_("synonym for --files-with-matches")),
-		OPT_BOOLEAN('L', "files-without-match",
+		OPT_BOOL('L', "files-without-match",
 			&opt.unmatch_name_only,
 			N_("show only the names of files without match")),
-		OPT_BOOLEAN('z', "null", &opt.null_following_name,
+		OPT_BOOL('z', "null", &opt.null_following_name,
 			N_("print NUL after filenames")),
-		OPT_BOOLEAN('c', "count", &opt.count,
+		OPT_BOOL('c', "count", &opt.count,
 			N_("show the number of matches instead of matching lines")),
 		OPT__COLOR(&opt.color, N_("highlight matches")),
-		OPT_BOOLEAN(0, "break", &opt.file_break,
+		OPT_BOOL(0, "break", &opt.file_break,
 			N_("print empty line between matches from different files")),
-		OPT_BOOLEAN(0, "heading", &opt.heading,
+		OPT_BOOL(0, "heading", &opt.heading,
 			N_("show filename only once above matches from same file")),
 		OPT_GROUP(""),
 		OPT_CALLBACK('C', "context", &opt, N_("n"),
@@ -706,9 +706,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 			N_("show <n> context lines after matches")),
 		OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
 			context_callback),
-		OPT_BOOLEAN('p', "show-function", &opt.funcname,
+		OPT_BOOL('p', "show-function", &opt.funcname,
 			N_("show a line with the function name before matches")),
-		OPT_BOOLEAN('W', "function-context", &opt.funcbody,
+		OPT_BOOL('W', "function-context", &opt.funcbody,
 			N_("show the surrounding function")),
 		OPT_GROUP(""),
 		OPT_CALLBACK('f', NULL, &opt, N_("file"),
@@ -718,7 +718,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 0, "and", &opt, NULL,
 		  N_("combine patterns specified with -e"),
 		  PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
-		OPT_BOOLEAN(0, "or", &dummy, ""),
+		OPT_BOOL(0, "or", &dummy, ""),
 		{ OPTION_CALLBACK, 0, "not", &opt, NULL, "",
 		  PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
 		{ OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
@@ -729,7 +729,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		  close_callback },
 		OPT__QUIET(&opt.status_only,
 			   N_("indicate hit with exit status without output")),
-		OPT_BOOLEAN(0, "all-match", &opt.all_match,
+		OPT_BOOL(0, "all-match", &opt.all_match,
 			N_("show only matches from files that match all patterns")),
 		{ OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
 		  N_("show parse tree for grep expression"),
@@ -738,8 +738,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		{ OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
 			N_("pager"), N_("show matching files in the pager"),
 			PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
-		OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed__ignored,
-			    N_("allow calling of grep(1) (ignored by this build)")),
+		OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored,
+			 N_("allow calling of grep(1) (ignored by this build)")),
 		{ OPTION_CALLBACK, 0, "help-all", &options, NULL, N_("show usage"),
 		  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
 		OPT_END()
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 8d184f1..4aea5bb 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -70,10 +70,10 @@ static const char *vpath;
 
 static const struct option hash_object_options[] = {
 	OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
-	OPT_BOOLEAN('w', NULL, &write_object, N_("write the object into the object database")),
+	OPT_BOOL('w', NULL, &write_object, N_("write the object into the object database")),
 	OPT_BOOLEAN( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
-	OPT_BOOLEAN( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
-	OPT_BOOLEAN( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
+	OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
+	OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
 	OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")),
 	OPT_END()
 };
diff --git a/builtin/log.c b/builtin/log.c
index 05e374d..1dafbd0 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1179,10 +1179,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
 			    N_("don't strip/add [PATCH]"),
 			    PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
-		OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
-			    N_("don't output binary diffs")),
-		OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
-			    N_("don't include a patch matching a commit upstream")),
+		OPT_BOOL(0, "no-binary", &no_binary_diff,
+			 N_("don't output binary diffs")),
+		OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
+			 N_("don't include a patch matching a commit upstream")),
 		{ OPTION_SET_INT, 'p', "no-stat", &use_patch_format, NULL,
 		  N_("show patch format instead of default (patch + stat)"),
 		  PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1},
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 5cf3e31..963ccc9 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -461,24 +461,24 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
 			N_("paths are separated with NUL character"),
 			PARSE_OPT_NOARG, option_parse_z },
-		OPT_BOOLEAN('t', NULL, &show_tag,
+		OPT_BOOL('t', NULL, &show_tag,
 			N_("identify the file status with tags")),
-		OPT_BOOLEAN('v', NULL, &show_valid_bit,
+		OPT_BOOL('v', NULL, &show_valid_bit,
 			N_("use lowercase letters for 'assume unchanged' files")),
-		OPT_BOOLEAN('c', "cached", &show_cached,
+		OPT_BOOL('c', "cached", &show_cached,
 			N_("show cached files in the output (default)")),
-		OPT_BOOLEAN('d', "deleted", &show_deleted,
+		OPT_BOOL('d', "deleted", &show_deleted,
 			N_("show deleted files in the output")),
-		OPT_BOOLEAN('m', "modified", &show_modified,
+		OPT_BOOL('m', "modified", &show_modified,
 			N_("show modified files in the output")),
-		OPT_BOOLEAN('o', "others", &show_others,
+		OPT_BOOL('o', "others", &show_others,
 			N_("show other files in the output")),
 		OPT_BIT('i', "ignored", &dir.flags,
 			N_("show ignored files in the output"),
 			DIR_SHOW_IGNORED),
-		OPT_BOOLEAN('s', "stage", &show_stage,
+		OPT_BOOL('s', "stage", &show_stage,
 			N_("show staged contents' object name in the output")),
-		OPT_BOOLEAN('k', "killed", &show_killed,
+		OPT_BOOL('k', "killed", &show_killed,
 			N_("show files on the filesystem that need to be removed")),
 		OPT_BIT(0, "directory", &dir.flags,
 			N_("show 'other' directories' name only"),
@@ -486,9 +486,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		OPT_NEGBIT(0, "empty-directory", &dir.flags,
 			N_("don't show empty directories"),
 			DIR_HIDE_EMPTY_DIRECTORIES),
-		OPT_BOOLEAN('u', "unmerged", &show_unmerged,
+		OPT_BOOL('u', "unmerged", &show_unmerged,
 			N_("show unmerged files in the output")),
-		OPT_BOOLEAN(0, "resolve-undo", &show_resolve_undo,
+		OPT_BOOL(0, "resolve-undo", &show_resolve_undo,
 			    N_("show resolve-undo information")),
 		{ OPTION_CALLBACK, 'x', "exclude", &exclude_list, N_("pattern"),
 			N_("skip files matching pattern"),
@@ -504,12 +504,12 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		{ OPTION_SET_INT, 0, "full-name", &prefix_len, NULL,
 			N_("make the output relative to the project top directory"),
 			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
-		OPT_BOOLEAN(0, "error-unmatch", &error_unmatch,
+		OPT_BOOL(0, "error-unmatch", &error_unmatch,
 			N_("if any <file> is not in the index, treat this as an error")),
 		OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
 			N_("pretend that paths removed since <tree-ish> are still present")),
 		OPT__ABBREV(&abbrev),
-		OPT_BOOLEAN(0, "debug", &debug_mode, N_("show debugging data")),
+		OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
 		OPT_END()
 	};
 
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index fb76e38..de88563 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -138,9 +138,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 			LS_NAME_ONLY),
 		OPT_SET_INT(0, "full-name", &chomp_prefix,
 			    N_("use full path names"), 0),
-		OPT_BOOLEAN(0, "full-tree", &full_tree,
-			    N_("list entire tree; not just current directory "
-			       "(implies --full-name)")),
+		OPT_BOOL(0, "full-tree", &full_tree,
+			 N_("list entire tree; not just current directory "
+			    "(implies --full-name)")),
 		OPT__ABBREV(&abbrev),
 		OPT_END()
 	};
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 0c4cd2f..e88eb93 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -95,11 +95,11 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
 	int is_ancestor = 0;
 
 	struct option options[] = {
-		OPT_BOOLEAN('a', "all", &show_all, N_("output all common ancestors")),
-		OPT_BOOLEAN(0, "octopus", &octopus, N_("find ancestors for a single n-way merge")),
-		OPT_BOOLEAN(0, "independent", &reduce, N_("list revs not reachable from others")),
-		OPT_BOOLEAN(0, "is-ancestor", &is_ancestor,
-			    N_("is the first one ancestor of the other?")),
+		OPT_BOOL('a', "all", &show_all, N_("output all common ancestors")),
+		OPT_BOOL(0, "octopus", &octopus, N_("find ancestors for a single n-way merge")),
+		OPT_BOOL(0, "independent", &reduce, N_("list revs not reachable from others")),
+		OPT_BOOL(0, "is-ancestor", &is_ancestor,
+			 N_("is the first one ancestor of the other?")),
 		OPT_END()
 	};
 
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index c0570f2..844f84f 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -30,7 +30,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 	int quiet = 0;
 	int prefixlen = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('p', "stdout", &to_stdout, N_("send results to standard output")),
+		OPT_BOOL('p', "stdout", &to_stdout, N_("send results to standard output")),
 		OPT_SET_INT(0, "diff3", &xmp.style, N_("use a diff3 based merge"), XDL_MERGE_DIFF3),
 		OPT_SET_INT(0, "ours", &xmp.favor, N_("for conflicts, use our version"),
 			    XDL_MERGE_FAVOR_OURS),
diff --git a/builtin/merge.c b/builtin/merge.c
index 34a6166..a8cf4a2 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -197,15 +197,15 @@ static struct option builtin_merge_options[] = {
 	{ OPTION_CALLBACK, 'n', NULL, NULL, NULL,
 		N_("do not show a diffstat at the end of the merge"),
 		PARSE_OPT_NOARG, option_parse_n },
-	OPT_BOOLEAN(0, "stat", &show_diffstat,
+	OPT_BOOL(0, "stat", &show_diffstat,
 		N_("show a diffstat at the end of the merge")),
-	OPT_BOOLEAN(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
+	OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
 	{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
 	  N_("add (at most <n>) entries from shortlog to merge commit message"),
 	  PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
-	OPT_BOOLEAN(0, "squash", &squash,
+	OPT_BOOL(0, "squash", &squash,
 		N_("create a single commit instead of doing a merge")),
-	OPT_BOOLEAN(0, "commit", &option_commit,
+	OPT_BOOL(0, "commit", &option_commit,
 		N_("perform a commit if the merge succeeds (default)")),
 	OPT_BOOL('e', "edit", &option_edit,
 		N_("edit message before committing")),
@@ -224,12 +224,12 @@ static struct option builtin_merge_options[] = {
 		N_("merge commit message (for a non-fast-forward merge)"),
 		option_parse_message),
 	OPT__VERBOSITY(&verbosity),
-	OPT_BOOLEAN(0, "abort", &abort_current_merge,
+	OPT_BOOL(0, "abort", &abort_current_merge,
 		N_("abort the current in-progress merge")),
 	OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
 	{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
 	  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-	OPT_BOOLEAN(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
+	OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
 	OPT_END()
 };
 
diff --git a/builtin/mv.c b/builtin/mv.c
index 034fec9..be6fa77 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -62,7 +62,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 		OPT__VERBOSE(&verbose, N_("be verbose")),
 		OPT__DRY_RUN(&show_only, N_("dry run")),
 		OPT__FORCE(&force, N_("force move/rename even if target exists")),
-		OPT_BOOLEAN('k', NULL, &ignore_errors, N_("skip move/rename errors")),
+		OPT_BOOL('k', NULL, &ignore_errors, N_("skip move/rename errors")),
 		OPT_END(),
 	};
 	const char **source, **destination, **dest_path;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 0aaa19e..a908a34 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -310,15 +310,15 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 	int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
 	struct name_ref_data data = { 0, 0, NULL };
 	struct option opts[] = {
-		OPT_BOOLEAN(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
-		OPT_BOOLEAN(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
+		OPT_BOOL(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
+		OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
 		OPT_STRING(0, "refs", &data.ref_filter, N_("pattern"),
 				   N_("only use refs matching <pattern>")),
 		OPT_GROUP(""),
-		OPT_BOOLEAN(0, "all", &all, N_("list all commits reachable from all refs")),
-		OPT_BOOLEAN(0, "stdin", &transform_stdin, N_("read from stdin")),
-		OPT_BOOLEAN(0, "undefined", &allow_undefined, N_("allow to print `undefined` names")),
-		OPT_BOOLEAN(0, "always",     &always,
+		OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
+		OPT_BOOL(0, "stdin", &transform_stdin, N_("read from stdin")),
+		OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
+		OPT_BOOL(0, "always",     &always,
 			   N_("show abbreviated commit object as fallback")),
 		{
 			/* A Hidden OPT_BOOL */
diff --git a/builtin/notes.c b/builtin/notes.c
index 8f63cb2..d459e23 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -483,7 +483,7 @@ static int copy(int argc, const char **argv, const char *prefix)
 	const char *rewrite_cmd = NULL;
 	struct option options[] = {
 		OPT__FORCE(&force, N_("replace existing notes")),
-		OPT_BOOLEAN(0, "stdin", &from_stdin, N_("read objects from stdin")),
+		OPT_BOOL(0, "stdin", &from_stdin, N_("read objects from stdin")),
 		OPT_STRING(0, "for-rewrite", &rewrite_cmd, N_("command"),
 			   N_("load rewriting config for <command> (implies "
 			      "--stdin)")),
@@ -853,7 +853,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
 		OPT_BIT(0, "ignore-missing", &flag,
 			N_("attempt to remove non-existent note is not an error"),
 			IGNORE_MISSING),
-		OPT_BOOLEAN(0, "stdin", &from_stdin,
+		OPT_BOOL(0, "stdin", &from_stdin,
 			    N_("read object names from the standard input")),
 		OPT_END()
 	};
diff --git a/builtin/push.c b/builtin/push.c
index 6d36c24..bebaf3d 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -446,15 +446,15 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
 		OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
 			    (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
-		OPT_BOOLEAN( 0, "delete", &deleterefs, N_("delete refs")),
-		OPT_BOOLEAN( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
+		OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")),
+		OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
 		OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
 		OPT_BIT( 0,  "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
 		OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
 		{ OPTION_CALLBACK, 0, "recurse-submodules", &flags, N_("check"),
 			N_("control recursive pushing of submodules"),
 			PARSE_OPT_OPTARG, option_parse_recurse_submodules },
-		OPT_BOOLEAN( 0 , "thin", &thin, N_("use thin pack")),
+		OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")),
 		OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
 		OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
 		OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
diff --git a/builtin/remote.c b/builtin/remote.c
index 5e54d36..eaac3e2 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -160,7 +160,7 @@ static int add(int argc, const char **argv)
 	int i;
 
 	struct option options[] = {
-		OPT_BOOLEAN('f', "fetch", &fetch, N_("fetch the remote branches")),
+		OPT_BOOL('f', "fetch", &fetch, N_("fetch the remote branches")),
 		OPT_SET_INT(0, "tags", &fetch_tags,
 			    N_("import all tags and associated objects when fetching"),
 			    TAGS_SET),
@@ -1088,7 +1088,7 @@ static int show(int argc, const char **argv)
 {
 	int no_query = 0, result = 0, query_flag = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('n', NULL, &no_query, N_("do not query remotes")),
+		OPT_BOOL('n', NULL, &no_query, N_("do not query remotes")),
 		OPT_END()
 	};
 	struct ref_states states;
@@ -1195,10 +1195,10 @@ static int set_head(int argc, const char **argv)
 	char *head_name = NULL;
 
 	struct option options[] = {
-		OPT_BOOLEAN('a', "auto", &opt_a,
-			    N_("set refs/remotes/<name>/HEAD according to remote")),
-		OPT_BOOLEAN('d', "delete", &opt_d,
-			    N_("delete refs/remotes/<name>/HEAD")),
+		OPT_BOOL('a', "auto", &opt_a,
+			 N_("set refs/remotes/<name>/HEAD according to remote")),
+		OPT_BOOL('d', "delete", &opt_d,
+			 N_("delete refs/remotes/<name>/HEAD")),
 		OPT_END()
 	};
 	argc = parse_options(argc, argv, NULL, options, builtin_remote_sethead_usage,
@@ -1317,8 +1317,8 @@ static int update(int argc, const char **argv)
 {
 	int i, prune = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('p', "prune", &prune,
-			    N_("prune remotes after fetching")),
+		OPT_BOOL('p', "prune", &prune,
+			 N_("prune remotes after fetching")),
 		OPT_END()
 	};
 	const char **fetch_argv;
@@ -1404,7 +1404,7 @@ static int set_branches(int argc, const char **argv)
 {
 	int add_mode = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('\0', "add", &add_mode, N_("add branch")),
+		OPT_BOOL('\0', "add", &add_mode, N_("add branch")),
 		OPT_END()
 	};
 
@@ -1432,11 +1432,11 @@ static int set_url(int argc, const char **argv)
 	int urlset_nr;
 	struct strbuf name_buf = STRBUF_INIT;
 	struct option options[] = {
-		OPT_BOOLEAN('\0', "push", &push_mode,
-			    N_("manipulate push URLs")),
-		OPT_BOOLEAN('\0', "add", &add_mode,
-			    N_("add URL")),
-		OPT_BOOLEAN('\0', "delete", &delete_mode,
+		OPT_BOOL('\0', "push", &push_mode,
+			 N_("manipulate push URLs")),
+		OPT_BOOL('\0', "add", &add_mode,
+			 N_("add URL")),
+		OPT_BOOL('\0', "delete", &delete_mode,
 			    N_("delete URLs")),
 		OPT_END()
 	};
diff --git a/builtin/replace.c b/builtin/replace.c
index 59d3115..11b0a55 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -118,9 +118,9 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
 {
 	int list = 0, delete = 0, force = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('l', NULL, &list, N_("list replace refs")),
-		OPT_BOOLEAN('d', NULL, &delete, N_("delete replace refs")),
-		OPT_BOOLEAN('f', NULL, &force, N_("replace the ref if it exists")),
+		OPT_BOOL('l', NULL, &list, N_("list replace refs")),
+		OPT_BOOL('d', NULL, &delete, N_("delete replace refs")),
+		OPT_BOOL('f', NULL, &force, N_("replace the ref if it exists")),
 		OPT_END()
 	};
 
diff --git a/builtin/reset.c b/builtin/reset.c
index afa6e02..0905815 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -258,7 +258,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				N_("reset HEAD, index and working tree"), MERGE),
 		OPT_SET_INT(0, "keep", &reset_type,
 				N_("reset HEAD but keep local changes"), KEEP),
-		OPT_BOOLEAN('p', "patch", &patch_mode, N_("select hunks interactively")),
+		OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
 		OPT_END()
 	};
 
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index de894c7..67e8ccf 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -346,9 +346,9 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 		NULL
 	};
 	static struct option parseopt_opts[] = {
-		OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
+		OPT_BOOL(0, "keep-dashdash", &keep_dashdash,
 					N_("keep the `--` passed as an arg")),
-		OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option,
+		OPT_BOOL(0, "stop-at-non-option", &stop_at_non_option,
 					N_("stop parsing after the "
 					   "first non-option argument")),
 		OPT_END(),
diff --git a/builtin/rm.c b/builtin/rm.c
index 18916e0..ce28fa9 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -268,10 +268,10 @@ static int ignore_unmatch = 0;
 static struct option builtin_rm_options[] = {
 	OPT__DRY_RUN(&show_only, N_("dry run")),
 	OPT__QUIET(&quiet, N_("do not list removed files")),
-	OPT_BOOLEAN( 0 , "cached",         &index_only, N_("only remove from the index")),
+	OPT_BOOL( 0 , "cached",         &index_only, N_("only remove from the index")),
 	OPT__FORCE(&force, N_("override the up-to-date check")),
-	OPT_BOOLEAN('r', NULL,             &recursive,  N_("allow recursive removal")),
-	OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
+	OPT_BOOL('r', NULL,             &recursive,  N_("allow recursive removal")),
+	OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch,
 				N_("exit with a zero status even if nothing matched")),
 	OPT_END(),
 };
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 1434f8f..ae73d17 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -224,12 +224,12 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
 	int nongit = !startup_info->have_repository;
 
 	static const struct option options[] = {
-		OPT_BOOLEAN('n', "numbered", &log.sort_by_number,
-			    N_("sort output according to the number of commits per author")),
-		OPT_BOOLEAN('s', "summary", &log.summary,
-			    N_("Suppress commit descriptions, only provides commit count")),
-		OPT_BOOLEAN('e', "email", &log.email,
-			    N_("Show the email address of each author")),
+		OPT_BOOL('n', "numbered", &log.sort_by_number,
+			 N_("sort output according to the number of commits per author")),
+		OPT_BOOL('s', "summary", &log.summary,
+			 N_("Suppress commit descriptions, only provides commit count")),
+		OPT_BOOL('e', "email", &log.email,
+			 N_("Show the email address of each author")),
 		{ OPTION_CALLBACK, 'w', NULL, &log, N_("w[,i1[,i2]]"),
 			N_("Linewrap output"), PARSE_OPT_OPTARG, &parse_wrap_args },
 		OPT_END(),
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 9788eb1..001f29c 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -646,30 +646,30 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 	int dense = 1;
 	const char *reflog_base = NULL;
 	struct option builtin_show_branch_options[] = {
-		OPT_BOOLEAN('a', "all", &all_heads,
-			    N_("show remote-tracking and local branches")),
-		OPT_BOOLEAN('r', "remotes", &all_remotes,
-			    N_("show remote-tracking branches")),
+		OPT_BOOL('a', "all", &all_heads,
+			 N_("show remote-tracking and local branches")),
+		OPT_BOOL('r', "remotes", &all_remotes,
+			 N_("show remote-tracking branches")),
 		OPT__COLOR(&showbranch_use_color,
 			    N_("color '*!+-' corresponding to the branch")),
 		{ OPTION_INTEGER, 0, "more", &extra, N_("n"),
 			    N_("show <n> more commits after the common ancestor"),
 			    PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
 		OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1),
-		OPT_BOOLEAN(0, "no-name", &no_name, N_("suppress naming strings")),
-		OPT_BOOLEAN(0, "current", &with_current_branch,
-			    N_("include the current branch")),
-		OPT_BOOLEAN(0, "sha1-name", &sha1_name,
-			    N_("name commits with their object names")),
-		OPT_BOOLEAN(0, "merge-base", &merge_base,
-			    N_("show possible merge bases")),
-		OPT_BOOLEAN(0, "independent", &independent,
+		OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")),
+		OPT_BOOL(0, "current", &with_current_branch,
+			 N_("include the current branch")),
+		OPT_BOOL(0, "sha1-name", &sha1_name,
+			 N_("name commits with their object names")),
+		OPT_BOOL(0, "merge-base", &merge_base,
+			 N_("show possible merge bases")),
+		OPT_BOOL(0, "independent", &independent,
 			    N_("show refs unreachable from any other ref")),
 		OPT_SET_INT(0, "topo-order", &sort_order,
 			    N_("show commits in topological order"),
 			    REV_SORT_IN_GRAPH_ORDER),
-		OPT_BOOLEAN(0, "topics", &topics,
-			    N_("show only commits not on the first branch")),
+		OPT_BOOL(0, "topics", &topics,
+			 N_("show only commits not on the first branch")),
 		OPT_SET_INT(0, "sparse", &dense,
 			    N_("show merges reachable from only one tip"), 0),
 		OPT_SET_INT(0, "date-order", &sort_order,
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 18680bb..9f3f5e3 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -165,15 +165,15 @@ static int help_callback(const struct option *opt, const char *arg, int unset)
 }
 
 static const struct option show_ref_options[] = {
-	OPT_BOOLEAN(0, "tags", &tags_only, N_("only show tags (can be combined with heads)")),
-	OPT_BOOLEAN(0, "heads", &heads_only, N_("only show heads (can be combined with tags)")),
-	OPT_BOOLEAN(0, "verify", &verify, N_("stricter reference checking, "
+	OPT_BOOL(0, "tags", &tags_only, N_("only show tags (can be combined with heads)")),
+	OPT_BOOL(0, "heads", &heads_only, N_("only show heads (can be combined with tags)")),
+	OPT_BOOL(0, "verify", &verify, N_("stricter reference checking, "
 		    "requires exact ref path")),
 	OPT_HIDDEN_BOOL('h', NULL, &show_head,
 			N_("show the HEAD reference, even if it would be filtered out")),
-	OPT_BOOLEAN(0, "head", &show_head,
+	OPT_BOOL(0, "head", &show_head,
 	  N_("show the HEAD reference, even if it would be filtered out")),
-	OPT_BOOLEAN('d', "dereference", &deref_tags,
+	OPT_BOOL('d', "dereference", &deref_tags,
 		    N_("dereference tags into object IDs")),
 	{ OPTION_CALLBACK, 's', "hash", &abbrev, N_("n"),
 	  N_("only show SHA1 hash using <n> digits"),
diff --git a/builtin/tag.c b/builtin/tag.c
index d8ae5aa..b577af5 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -450,12 +450,12 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_CMDMODE('v', "verify", &cmdmode, N_("verify tags"), 'v'),
 
 		OPT_GROUP(N_("Tag creation options")),
-		OPT_BOOLEAN('a', "annotate", &annotate,
+		OPT_BOOL('a', "annotate", &annotate,
 					N_("annotated tag, needs a message")),
 		OPT_CALLBACK('m', "message", &msg, N_("message"),
 			     N_("tag message"), parse_msg_arg),
 		OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
-		OPT_BOOLEAN('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
+		OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
 		OPT_STRING(0, "cleanup", &cleanup_arg, N_("mode"),
 			N_("how to strip spaces and #comments from message")),
 		OPT_STRING('u', "local-user", &keyid, N_("key id"),
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 51d2684..7484d36 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -16,8 +16,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 	int delete = 0, no_deref = 0, flags = 0;
 	struct option options[] = {
 		OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
-		OPT_BOOLEAN('d', NULL, &delete, N_("delete the reference")),
-		OPT_BOOLEAN( 0 , "no-deref", &no_deref,
+		OPT_BOOL('d', NULL, &delete, N_("delete the reference")),
+		OPT_BOOL( 0 , "no-deref", &no_deref,
 					N_("update <refname> not the one it points to")),
 		OPT_END(),
 	};
-- 
1.8.4.rc0.1.g8f6a3e5

^ permalink raw reply related	[relevance 3%]

* Re: [PATCH] tag: Use OPT_BOOL instead of OPT_BOOLEAN to allow one action multiple times
  @ 2013-07-31 23:10  5%         ` Junio C Hamano
  2013-08-17 15:01  4%           ` Stefano Lattarini
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2013-07-31 23:10 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git

Stefan Beller <stefanbeller@googlemail.com> writes:

> On 07/31/13 00:28, Junio C Hamano wrote:
>> 
>> we could just do
>> 
>> #define OPT_CMDMODE(s, l, v, h) \
>>     { OPTION_CMDMODE, (s), (l), (v), NULL, \
>>       (h), PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, (s) }
>> 
>
> I agree that's a better proposal than mine.

By the way, I haven't convinced myself that it is a good idea in
general to encourage more use of command mode options, so I am a bit
reluctant to add this before knowing which direction in the longer
term we are going.

 - Some large-ish Git subcommands, like "git submodule", use the
   mode word (e.g. "git submodule status") to specify the operation
   mode (youe could consider "status" a subsubcommand that
   "submodule" subcommand takes).  These commands typically began
   their life from day one with the mode words.

 - On the other hand, many Git subcommands, like "git tag", have
   "the primary operation mode" (e.g. "create a new one" is the
   primary operation mode for "git tag"), and use command mode
   options to specify other operation modes (e.g. "--delete").
   These commands started as single purpose commands (i.e. to
   perform their "primary operation") but have organically grown
   over time and acquired command mode options to invoke their
   secondary operations.

As an end user, you need to learn which style each command takes,
which is an unnecessary burden at the UI level.  In the longer term,
we may want to consider picking a single style, and migrating
everybody to it.  If I have to vote today, I would say we should
teach "git submodule" to also take command mode options (e.g. "git
submodule --status" will be understood the same way as "git
submodule status"), make them issue warnings when mode words are
used and encourage users to use command mode options instead, and
optionally remove the support of mode words at a large version bump
like 3.0.

One clear advantage mode words have over command mode options is
that there is no room for end user confusion.  The first word after
"git subcmd" is the mode word, and you will not even dream of asking
"what would 'git submodule add del foo' do?" as it is nonsensical.
The command mode options, on the other hand, gives too much useless
flexibility to ask for nonsense, e.g. "git tag --delete --verify",
"git tag --no-delete --delete", etc., and extra code needs to detect
and reject combinations.  But commands that took mode options cannot
be easily migrated to take mode words without hurting existing users
and scripts (e.g. "git tag delete master" can never be a request to
delete the tag 'master', as it is a request to create a tag whose
name is 'delete' that points at the same object as 'master' points
at).

^ permalink raw reply	[relevance 5%]

* [ANNOUNCE] Git v1.8.4-rc1
@ 2013-08-01 21:14  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2013-08-01 21:14 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate for Git v1.8.4-rc1 is now available for testing
at the usual places.

The release tarballs are found at:

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

and their SHA-1 checksums are:

ab0bb0ed36dd9c0d6425f64021a9c7d7311a2b5c  git-1.8.4.rc1.tar.gz
2d3f1f07ed3bde56fac5e823be7d71bf5bf0f743  git-htmldocs-1.8.4.rc1.tar.gz
c21f40d9cd2bbf7c28be4d32a1ae1ad98c198d96  git-manpages-1.8.4.rc1.tar.gz

The following public repositories all have a copy of the v1.8.4-rc1
tag and the master branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v1.8.4 Release Notes (draft)
========================

Backward compatibility notes (for Git 2.0)
------------------------------------------

When "git push [$there]" does not say what to push, we have used the
traditional "matching" semantics so far (all your branches were sent
to the remote as long as there already are branches of the same name
over there).  In Git 2.0, the default will change to the "simple"
semantics that pushes:

 - only the current branch to the branch with the same name, and only
   when the current branch is set to integrate with that remote
   branch, if you are pushing to the same remote as you fetch from; or

 - only the current branch to the branch with the same name, if you
   are pushing to a remote that is not where you usually fetch from.

Use the user preference configuration variable "push.default" to
change this.  If you are an old-timer who is used to the "matching"
semantics, you can set the variable to "matching" to keep the
traditional behaviour.  If you want to live in the future early, you
can set it to "simple" today without waiting for Git 2.0.

When "git add -u" (and "git add -A") is run inside a subdirectory and
does not specify which paths to add on the command line, it
will operate on the entire tree in Git 2.0 for consistency
with "git commit -a" and other commands.  There will be no
mechanism to make plain "git add -u" behave like "git add -u .".
Current users of "git add -u" (without a pathspec) should start
training their fingers to explicitly say "git add -u ."
before Git 2.0 comes.  A warning is issued when these commands are
run without a pathspec and when you have local changes outside the
current directory, because the behaviour in Git 2.0 will be different
from today's version in such a situation.

In Git 2.0, "git add <path>" will behave as "git add -A <path>", so
that "git add dir/" will notice paths you removed from the directory
and record the removal.  Versions before Git 2.0, including this
release, will keep ignoring removals, but the users who rely on this
behaviour are encouraged to start using "git add --ignore-removal <path>"
now before 2.0 is released.


Updates since v1.8.3
--------------------

Foreign interfaces, subsystems and ports.

 * Cygwin port has been updated for more recent Cygwin 1.7.

 * "git rebase -i" now honors --strategy and -X options.

 * Git-gui has been updated to its 0.18.0 version.

 * MediaWiki remote helper (in contrib/) has been updated to use the
   credential helper interface from Git.pm.

 * Update build for Cygwin 1.[57].  Torsten Bögershausen reports that
   this is fine with Cygwin 1.7 ($gmane/225824) so let's try moving it
   ahead.

 * The credential helper to talk to keychain on OS X (in contrib/) has
   been updated to kick in not just when talking http/https but also
   imap(s) and smtp.

 * Remote transport helper has been updated to report errors and
   maintain ref hierarchy used to keep track of its own state better.

 * With "export" remote-helper protocol, (1) a push that tries to
   update a remote ref whose name is different from the pushing side
   does not work yet, and (2) the helper may not know how to do
   --dry-run; these problematic cases are disabled for now.

 * git-remote-hg/bzr (in contrib/) updates.

 * git-remote-mw (in contrib/) hints users to check the certificate,
   when https:// connection failed.

 * git-remote-mw (in contrib/) adds a command to allow previewing the
   contents locally before pushing it out, when working with a
   MediaWiki remote.


UI, Workflows & Features

 * Sample "post-receive-email" hook script got an enhanced replacement
   "multimail" (in contrib/).

 * Also in contrib/ is a new "contacts" script that runs "git blame"
   to find out the people who may be interested in a set of changes.

 * "git clean" command learned an interactive mode.

 * The "--head" option to "git show-ref" was only to add "HEAD" to the
   list of candidate refs to be filtered by the usual rules
   (e.g. "--heads" that only show refs under refs/heads).  The meaning
   of the option has been changed to always show "HEAD" regardless of
   what filtering will be applied to any other ref.

   This is a backward incompatible change and might cause breakages to
   people's existing scripts.

 * "git show -s" was less discoverable than it should have been.  It
   now has a natural synonym "git show --no-patch".

 * "git check-mailmap" is a new command that lets you map usernames
   and e-mail addresses through the mailmap mechanism, just like many
   built-in commands do.

 * "git name-rev" learned to name an annotated tag object back to its
   tagname; "git name-rev $(git rev-parse v1.0.0)" gives "tags/v1.0.0",
   for example.

 * "git cat-file --batch-check=<format>" is added, primarily to allow
   on-disk footprint of objects in packfiles (often they are a lot
   smaller than their true size, when expressed as deltas) to be
   reported.

 * "git rebase [-i]" used to leave just "rebase" as its reflog messages
   for some operations. They have been reworded to be more informative.

 * In addition to the choice from "rebase, merge, or checkout-detach",
   "submodule update" can allow a custom command to be used in to
   update the working tree of submodules via the "submodule.*.update"
   configuration variable.

 * "git submodule update" can optionally clone the submodule
   repositories shallowly.

 * "git format-patch" learned "--from[=whom]" option, which sets the
   "From: " header to the specified person (or the person who runs the
   command, if "=whom" part is missing) and move the original author
   information to an in-body From: header as necessary.

 * The configuration variable "merge.ff" was cleary a tri-state to
   choose one from "favor fast-forward when possible", "always create
   a merge even when the history could fast-forward" and "do not
   create any merge, only update when the history fast-forwards", but
   the command line parser did not implement the usual convention of
   "last one wins, and command line overrides the configuration"
   correctly.

 * "gitweb" learned to optionally place extra links that point at the
   levels higher than the Gitweb pages themselves in the breadcrumbs,
   so that it can be used as part of a larger installation.

 * "git log --format=" now honors i18n.logoutputencoding configuration
   variable.

 * The "push.default=simple" mode of "git push" has been updated to
   behave like "current" without requiring a remote tracking
   information, when you push to a remote that is different from where
   you fetch from (i.e. a triangular workflow).

 * Having multiple "fixup!" on a line in the rebase instruction sheet
   did not work very well with "git rebase -i --autosquash".

 * "git log" learned the "--author-date-order" option, with which the
   output is topologically sorted and commits in parallel histories
   are shown intermixed together based on the author timestamp.

 * Various subcommands of "git submodule" refused to run from anywhere
   other than the top of the working tree of the superproject, but
   they have been taught to let you run from a subdirectory.

 * "git diff" learned a mode that ignores hunks whose change consists
   only of additions and removals of blank lines, which is the same as
   "diff -B" (ignore blank lines) of GNU diff.

 * "git rm" gives a single message followed by list of paths to report
   multiple paths that cannot be removed.

 * "git rebase" can be told with ":/look for this string" syntax commits
   to replay the changes onto and where the work to be replayed begins.

 * Many tutorials teach users to set "color.ui" to "auto" as the first
   thing after you set "user.name/email" to introduce yourselves to
   Git.  Now the variable defaults to "auto".

 * On Cygwin, "cygstart" is now recognised as a possible way to start
   a web browser (used in "help -w" and "instaweb" among others).

 * "git status" learned status.branch and status.short configuration
   variables to use --branch and --short options by default (override
   with --no-branch and --no-short options from the command line).

 * "git cmd <name>", when <name> happens to be a 40-hex string,
   directly uses the 40-hex string as an object name, even if a ref
   "refs/<some hierarchy>/<name>" exists.  This disambiguation order
   is unlikely to change, but we should warn about the ambiguity just
   like we warn when more than one refs/ hierarchies share the same
   name.

 * "git rebase" learned "--[no-]autostash" option to save local
   changes instead of refusing to run (to which people's normal
   response was to stash them and re-run).  This introduced a corner
   case breakage to "git am --abort" but it has been fixed.

 * Instead of typing four capital letters "HEAD", you can say "@" now,
   e.g. "git log @".

 * "check-ignore" (new feature since 1.8.2) has been updated to work
   more like "check-attr" over bidi-pipes.

 * "git describe" learned "--first-parent" option to limit its closest
   tagged commit search to the first-parent chain.

 * "git merge foo" that might have meant "git merge origin/foo" is
   diagnosed with a more informative error message.

 * "git log -L<line>,<range>:<filename>" has been added.  This may
   still have leaks and rough edges, though.

 * We used the approxidate() parser for "--expire=<timestamp>" options
   of various commands, but it is better to treat --expire=all and
   --expire=now a bit more specially than using the current timestamp.
   "git gc" and "git reflog" have been updated with a new parsing
   function for expiry dates.

 * Updates to completion (both bash and zsh) helpers.

 * The behaviour of the "--chain-reply-to" option of "git send-email"
   have changed at 1.7.0, and we added a warning/advice message to
   help users adjust to the new behaviour back then, but we kept it
   around for too long.  The message has finally been removed.

 * "git fetch origin master" unlike "git fetch origin" or "git fetch"
   did not update "refs/remotes/origin/master"; this was an early
   design decision to keep the update of remote tracking branches
   predictable, but in practice it turns out that people find it more
   convenient to opportunistically update them whenever we have a
   chance, and we have been updating them when we run "git push" which
   already breaks the original "predictability" anyway.

 * The configuration variable core.checkstat was advertised in the
   documentation but the code expected core.statinfo instead.
   For now, we accept both core.checkstat and core.statinfo, but the
   latter will be removed in the longer term.


Performance, Internal Implementation, etc.

 * The function attributes extensions are used to catch mistakes in
   use of our own variadic functions that use NULL sentinel at the end
   (i.e. like execl(3)) and format strings (i.e. like printf(3)).

 * The code to allow configuration data to be read from in-tree blob
   objects is in.  This may help working in a bare repository and
   submodule updates.

 * Fetching between repositories with many refs employed O(n^2)
   algorithm to match up the common objects, which has been corrected.

 * The original way to specify remote repository using .git/branches/
   used to have a nifty feature.  The code to support the feature was
   still in a function but the caller was changed not to call it 5
   years ago, breaking that feature and leaving the supporting code
   unreachable.  The dead code has been removed.

 * "git pack-refs" that races with new ref creation or deletion have
   been susceptible to lossage of refs under right conditions, which
   has been tightened up.

 * We read loose and packed rerferences in two steps, but after
   deciding to read a loose ref but before actually opening it to read
   it, another process racing with us can unlink it, which would cause
   us to barf.  The codepath has been updated to retry when such a
   race is detected, instead of outright failing.

 * Uses of the platform fnmatch(3) function (many places in the code,
   matching pathspec, .gitignore and .gitattributes to name a few)
   have been replaced with wildmatch, allowing "foo/**/bar" that would
   match foo/bar, foo/a/bar, foo/a/b/bar, etc.

 * Memory ownership and lifetime rules for what for-each-ref feeds to
   its callbacks have been clarified (in short, "you do not own it, so
   make a copy if you want to keep it").

 * The revision traversal logic to improve culling of irrelevant
   parents while traversing a mergy history has been updated.

 * Some leaks in unpack-trees (used in merge, cherry-pick and other
   codepaths) have been plugged.

 * The codepath to read from marks files in fast-import/export did not
   have to accept anything but 40-hex representation of the object
   name.  Further, fast-export did not need full in-core object
   representation to have parsed wen reading from them.  These
   codepaths have been optimized by taking advantage of these access
   patterns.

 * Object lookup logic, when the object hashtable starts to become
   crowded, has been optimized.

 * When TEST_OUTPUT_DIRECTORY setting is used, it was handled somewhat
   inconsistently between the test framework and t/Makefile, and logic
   to summarize the results looked at a wrong place.

 * "git clone" uses a lighter-weight implementation when making sure
   that the history behind refs are complete.

 * Many warnings from sparse source checker in compat/ area has been
   squelched.

 * The code to reading and updating packed-refs file has been updated,
   correcting corner case bugs.


Also contains various documentation updates and code clean-ups.


Fixes since v1.8.3
------------------

Unless otherwise noted, all the fixes since v1.8.3 in the maintenance
track are contained in this release (see release notes to them for
details).

 * Newer Net::SMTP::SSL module does not want the user programs to use
   the default behaviour to let server certificate go without
   verification, so by default enable the verification with a
   mechanism to turn it off if needed.
   (merge 35035bb rr/send-email-ssl-verify later to maint).

 * When "git" is spawned in such a way that any of the low 3 file
   descriptors is closed, our first open() may yield file descriptor 2,
   and writing error message to it would screw things up in a big way.
   (merge a11c396 tr/protect-low-3-fds later to maint).

 * The mailmap mechanism unnecessarily downcased the e-mail addresses
   in the output, and also ignored the human name when it is a single
   character name.
   (merge bd23794 jc/mailmap-case-insensitivity later to maint).

 * In two places we did not check return value (expected to be a file
   descriptor) correctly.
   (merge a77f106 tr/fd-gotcha-fixes later to maint).

 * Logic to auto-detect character encodings in the commit log message
   did not reject overlong and invalid UTF-8 characters.
   (merge 81050ac bc/commit-invalid-utf8 later to maint).

 * Pass port number as a separate argument when "send-email" initializes
   Net::SMTP, instead of as a part of the hostname, i.e. host:port.
   This allows GSSAPI codepath to match with the hostname given.
   (merge 1a741bf bc/send-email-use-port-as-separate-param later to maint).

 * "git diff" refused to even show difference when core.safecrlf is
   set to true (i.e. error out) and there are offending lines in the
   working tree files.
   (merge 5430bb2 jc/maint-diff-core-safecrlf later to maint).

 * A test that should have failed but didn't revealed a bug that needs
   to be corrected.
   (merge 94d75d1 jc/t1512-fix later to maint).

 * An overlong path to a .git directory may have overflown the
   temporary path buffer used to create a name for lockfiles.
   (merge 2fbd4f9 mh/maint-lockfile-overflow later to maint).

 * Invocations of "git checkout" used internally by "git rebase" were
   counted as "checkout", and affected later "git checkout -" to the
   the user to an unexpected place.
   (merge 3bed291 rr/rebase-checkout-reflog later to maint).

 * "git stash save", when your local change turns a tracked file into
   a directory, has to remove files in that directory in order to
   revert your working tree to a pristine state.  This will lose
   untracked files in such a directory, and the command now requires
   you to "--force" it.

 * The configuration variable column.ui was poorly documented.
   (merge 5e62cc1 rr/column-doc later to maint).

 * "git name-rev --refs=tags/v*" were forbidden, which was a bit
   inconvenient (you had to give a pattern to match refs fully, like
   --refs=refs/tags/v*).
   (merge 98c5c4a nk/name-rev-abbreviated-refs later to maint).

 * "git apply" parsed patches that add new files, generated by
   programs other than Git, incorrectly.  This is an old breakage in
   v1.7.11 and will need to be merged down to the maintanance tracks.

 * Older cURL wanted piece of memory we call it with to be stable, but
   we updated the auth material after handing it to a call.

 * "git pull" into nothing trashed "local changes" that were in the
   index, and this avoids it.

 * Many "git submodule" operations do not work on a submodule at a
   path whose name is not in ASCII.

 * "cherry-pick" had a small leak in an error codepath.

 * Logic used by git-send-email to suppress cc mishandled names like
   "A U. Thor" <author@example.xz>, where the human readable part
   needs to be quoted (the user input may not have the double quotes
   around the name, and comparison was done between quoted and
   unquoted strings).  It also mishandled names that need RFC2047
   quoting.

 * Call to discard_cache/discard_index (used when we use different
   contents of the index in-core, in many operations like commit,
   apply, and merge) used to leak memory that held the array of index
   entries, which has been plugged.
   (merge a0fc4db rs/discard-index-discard-array later to maint).

 * "gitweb" forgot to clear a global variable $search_regexp upon each
   request, mistakenly carrying over the previous search to a new one
   when used as a persistent CGI.

 * The wildmatch engine did not honor WM_CASEFOLD option correctly.

 * "git log -c --follow $path" segfaulted upon hitting the commit that
   renamed the $path being followed.

 * When a reflog notation is used for implicit "current branch", we
   did not say which branch and worse said "branch ''".

 * "difftool --dir-diff" did not copy back changes made by the
   end-user in the diff tool backend to the working tree in some
   cases.

 * "git push $there HEAD:branch" did not resolve HEAD early enough, so
   it was easy to flip it around while push is still going on and push
   out a branch that the user did not originally intended when the
   command was started.

 * The bash prompt code (in contrib/) displayed the name of the branch
   being rebased when "rebase -i/-m/-p" modes are in use, but not the
   plain vanilla "rebase".

 * Handling of negative exclude pattern for directories "!dir" was
   broken in the update to v1.8.3.

 * zsh prompt script that borrowed from bash prompt script did not
   work due to slight differences in array variable notation between
   these two shells.

 * An entry for "file://" scheme in the enumeration of URL types Git
   can take in the HTML documentation was made into a clickable link
   by mistake.

 * "git push --[no-]verify" was not documented.

 * Stop installing the git-remote-testpy script that is only used for
   testing.

 * "git commit --allow-empty-message -m ''" should not start an
   editor.

 * "git merge @{-1}~22" was rewritten to "git merge frotz@{1}~22"
   incorrectly when your previous branch was "frotz" (it should be
   rewritten to "git merge frotz~22" instead).

 * "git diff -c -p" was not showing a deleted line from a hunk when
   another hunk immediately begins where the earlier one ends.

 * "git log --ancestry-path A...B" did not work as expected, as it did
   not pay attention to the fact that the merge base between A and B
   was the bottom of the range being specified.

 * Mac OS X does not like to write(2) more than INT_MAX number of
   bytes; work it around by chopping write(2) into smaller pieces.

 * Newer MacOS X encourages the programs to compile and link with
   their CommonCrypto, not with OpenSSL.

 * "git clone foo/bar:baz" cannot be a request to clone from a remote
   over git-over-ssh specified in the scp style.  This case is now
   detected and clones from a local repository at "foo/bar:baz".

 * When $HOME is misconfigured to point at an unreadable directory, we
   used to complain and die. Loosen the check.

 * "git subtree" (in contrib/) had one codepath with loose error
   checks to lose data at the remote side.

 * "git fetch" into a shallow repository from a repository that does
   not know about the shallow boundary commits (e.g. a different fork
   from the repository the current shallow repository was cloned from)
   did not work correctly.

 * "git checkout foo" DWIMs the intended "upstream" and turns it into
   "git checkout -t -b foo remotes/origin/foo". This codepath has been
   updated to correctly take existing remote definitions into account.

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

Changes since v1.8.4-rc0 are as follows:

Brandon Casey (1):
      git-completion.bash: replace zsh notation that breaks bash 3.X

Daniele Segato (1):
      docs/git-tag: explain lightweight versus annotated tags

Jeff King (6):
      docs: fix 'report-status' protocol capability thinko
      docs: note that receive-pack knows side-band-64k capability
      document 'agent' protocol capability
      document 'quiet' receive-pack capability
      commit.h: drop redundant comment
      commit: tweak empty cherry pick advice for sequencer

Jiang Xin (2):
      Documentation/git-clean: fix description for range
      git-clean: implement partial matching for selection

Junio C Hamano (2):
      builtin/rm.c: consolidate error reporting for removing submodules
      Git 1.8.4-rc1

Lukas Fleischer (1):
      Avoid using `echo -n` anywhere

Maurício C Antunes (1):
      hg-to-git: --allow-empty-message in git commit

Michael Haggerty (1):
      do_one_ref(): save and restore value of current_ref

Michal Sojka (1):
      contrib/subtree: Fix make install target

Nguyễn Thái Ngọc Duy (1):
      document 'allow-tip-sha1-in-want' capability

Ondřej Bílka (1):
      many small typofixes

Ralf Thielow (1):
      git-rebase: fix typo

Ramkumar Ramachandra (1):
      config doc: quote paths, fixing tilde-interpretation

Ramsay Allan Jones (1):
      commit-slab.h: Fix memory allocation and addressing

Stefan Beller (1):
      .mailmap: combine more (email, name) to individual persons

Thomas Rast (1):
      Rename advice.object_name_warning to objectNameWarning

^ permalink raw reply	[relevance 2%]

* Re: Rewriting git-repack.sh in C
  @ 2013-08-02 16:36  1%   ` Duy Nguyen
  0 siblings, 0 replies; 200+ results
From: Duy Nguyen @ 2013-08-02 16:36 UTC (permalink / raw)
  To: Stefan Beller; +Cc: GIT Mailing-list

On Fri, Aug 02, 2013 at 09:10:59PM +0700, Duy Nguyen wrote:
> On Fri, Aug 2, 2013 at 8:48 PM, Stefan Beller
> <stefanbeller@googlemail.com> wrote:
> > Hello,
> >
> > I'd like to rewrite the repack shell script in C.
> > So I tried the naive approach reading the man page and
> > the script itself and write C program by matching each block/line
> > of the script with a function in C
> >
> > ...
> >
> > So my question is, how you'd generally approach rewriting a
> > shell script in C.
> 
> Start a new process via start_command/run_command interface. It's
> safer to retain the process boundary at this stage. You can try to
> integrate further later.

I was in the middle of something and somehow read this as "rewriting
git-rebase.sh" :-X

For git-repack, because it ends with a single pack-objects call, we
might not need a new process after all (very much like tail call
optimization). This is what I got for some time, but still not polish
it for submission (and it may be a bit broken after the last
rebase). Maybe you can work off this, or from scratch if you think
it's too messy. It basically teaches pack-objects extra features that
repack needs, then make repack a wrapper of pack-objects.

-- 8< --
commit 25569a3958c3272b3eb5fa50dea680948f7a2768 (build-in-repack)
Author: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date:   Wed Nov 9 19:21:39 2011 +0700

    Build in git-repack
    
    pack-objects learns a few more options to take over what's been done
    by git-repack.sh. cmd_repack() becomes a wrapper around
    cmd_pack_objects().

diff --git a/Makefile b/Makefile
index 0f931a2..b4010a6 100644
--- a/Makefile
+++ b/Makefile
@@ -460,7 +460,6 @@ SCRIPT_SH += git-mergetool.sh
 SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -584,6 +583,7 @@ BUILT_INS += git-init$X
 BUILT_INS += git-merge-subtree$X
 BUILT_INS += git-peek-remote$X
 BUILT_INS += git-repo-config$X
+BUILT_INS += git-repack$X
 BUILT_INS += git-show$X
 BUILT_INS += git-stage$X
 BUILT_INS += git-status$X
diff --git a/builtin.h b/builtin.h
index 64bab6b..feb958f 100644
--- a/builtin.h
+++ b/builtin.h
@@ -117,6 +117,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f069462..1742ea1 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -18,10 +18,17 @@
 #include "refs.h"
 #include "streaming.h"
 #include "thread-utils.h"
+#include "sigchain.h"
 
 static const char *pack_usage[] = {
 	N_("git pack-objects --stdout [options...] [< ref-list | < object-list]"),
 	N_("git pack-objects [options...] base-name [< ref-list | < object-list]"),
+	N_("git pack-objects --repack [options...]"),
+	NULL
+};
+
+static char const * const repack_usage[] = {
+	N_("git repack [options]"),
 	NULL
 };
 
@@ -103,6 +110,15 @@ static struct object_entry *locate_object_entry(const unsigned char *sha1);
 static uint32_t written, written_delta;
 static uint32_t reused, reused_delta;
 
+#define REPACK_IN_PROGRESS		(1 << 0)
+#define REPACK_UPDATE_INFO		(1 << 1)
+#define REPACK_ALL_INTO_ONE		(1 << 2)
+#define REPACK_REMOVE_REDUNDANT		(1 << 3)
+
+static int repack_flags, nr_written_packs;
+static int repack_usedeltabaseoffset;
+static struct string_list written_packs;
+static struct string_list backup_files;
 
 static void *get_delta(struct object_entry *entry)
 {
@@ -792,9 +808,19 @@ static void write_pack_file(void)
 			snprintf(tmpname, sizeof(tmpname), "%s-", base_name);
 			finish_tmp_packfile(tmpname, pack_tmp_name,
 					    written_list, nr_written,
-					    &pack_idx_opts, sha1);
+					    &pack_idx_opts, sha1,
+					    repack_flags & REPACK_IN_PROGRESS ?
+					    &backup_files : NULL);
 			free(pack_tmp_name);
-			puts(sha1_to_hex(sha1));
+			if (repack_flags & REPACK_IN_PROGRESS) {
+				int len = strlen(tmpname);
+				char *s = xmalloc(len + 2);
+				memcpy(s, tmpname, len - 4);
+				memcpy(s + len - 4, ".pack", 6);
+				string_list_append(&written_packs, s);
+				nr_written_packs++;
+			} else
+				puts(sha1_to_hex(sha1));
 		}
 
 		/* mark written objects as written to previous pack */
@@ -2359,7 +2385,8 @@ static void get_object_list(int ac, const char **av)
 	save_commit_buffer = 0;
 	setup_revisions(ac, av, &revs, NULL);
 
-	while (fgets(line, sizeof(line), stdin) != NULL) {
+	while (!(repack_flags & REPACK_IN_PROGRESS) &&
+	       fgets(line, sizeof(line), stdin) != NULL) {
 		int len = strlen(line);
 		if (len && line[len - 1] == '\n')
 			line[--len] = 0;
@@ -2387,6 +2414,30 @@ static void get_object_list(int ac, const char **av)
 		loosen_unused_packed_objects(&revs);
 }
 
+static void rollback_repack(void)
+{
+	struct strbuf dst = STRBUF_INIT;
+	int i, ret;
+	for (i = 0; i < backup_files.nr; i++) {
+		const char *src = backup_files.items[i].string;
+		strbuf_addstr(&dst, src);
+		strbuf_setlen(&dst, dst.len - 4); /* remove .old */
+		ret = rename(src, dst.buf);
+		if (ret)
+			warning("failed to restore %s: %s", src, strerror(errno));
+		strbuf_setlen(&dst, 0);
+	}
+	strbuf_release(&dst);
+	string_list_clear(&backup_files, 0);
+}
+
+static void rollback_repack_on_signal(int signo)
+{
+	rollback_repack();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
 static int option_parse_index_version(const struct option *opt,
 				      const char *arg, int unset)
 {
@@ -2436,11 +2487,12 @@ static int option_parse_ulong(const struct option *opt,
 
 int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 {
+	struct strbuf repack_base_name = STRBUF_INIT;
 	int use_internal_rev_list = 0;
 	int thin = 0;
 	int all_progress_implied = 0;
 	const char *rp_av[6];
-	int rp_ac = 0;
+	int i, rp_ac = 0;
 	int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
 	struct option pack_objects_options[] = {
 		OPT_SET_INT('q', "quiet", &progress,
@@ -2505,6 +2557,16 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 			    N_("pack compression level")),
 		OPT_SET_INT(0, "keep-true-parents", &grafts_replace_parents,
 			    N_("do not hide commits by grafts"), 0),
+
+		OPT_BIT(0, "repack", &repack_flags,
+			N_("repack mode"), REPACK_IN_PROGRESS),
+		OPT_BIT(0, "repack-all", &repack_flags,
+			N_("repack everything into one pack"), REPACK_ALL_INTO_ONE),
+		OPT_BIT(0, "remove-redundant", &repack_flags,
+			N_("remove redundant objects after repack"), REPACK_REMOVE_REDUNDANT),
+		OPT_BIT(0, "update-info", &repack_flags,
+			N_("run git-update-server-info after repack"), REPACK_UPDATE_INFO),
+
 		OPT_END(),
 	};
 
@@ -2556,6 +2618,36 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 	if (delta_search_threads != 1)
 		warning("no threads support, ignoring --threads");
 #endif
+	if ((repack_flags & REPACK_IN_PROGRESS) == 0 &&
+	    (repack_flags & ~REPACK_IN_PROGRESS))
+		die("--repack must be given for any repack related options");
+	if (repack_flags & REPACK_IN_PROGRESS) {
+		if (pack_to_stdout)
+			die("--stdout cannot be used with --repack");
+		if (argc)
+			die("base name cannot be used with --repack");
+
+		rp_av[rp_ac++] = "--all";
+		rp_av[rp_ac++] = "--reflog";
+		use_internal_rev_list = 1;
+
+		grafts_replace_parents = 0; /* --keep-true-parents */
+		ignore_packed_keep = 1;	    /* --honor-pack-keep */
+		non_empty = 1;		    /* --non-empty */
+
+		if (!(repack_flags & REPACK_ALL_INTO_ONE)) {
+			incremental = 1; /* --incremental */
+			rp_av[rp_ac++] = "--unpacked";
+		}
+
+		strbuf_addf(&repack_base_name,
+			    "%s/pack/pack", get_object_directory());
+		base_name = repack_base_name.buf;
+
+		sigchain_push_common(rollback_repack_on_signal);
+		atexit(rollback_repack);
+	}
+
 	if (!pack_to_stdout && !pack_size_limit)
 		pack_size_limit = pack_size_limit_cfg;
 	if (pack_to_stdout && pack_size_limit)
@@ -2598,5 +2690,184 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		fprintf(stderr, "Total %"PRIu32" (delta %"PRIu32"),"
 			" reused %"PRIu32" (delta %"PRIu32")\n",
 			written, written_delta, reused, reused_delta);
+
+	if (!(repack_flags & REPACK_IN_PROGRESS))
+		return 0;
+
+	if (!nr_written_packs) {
+		printf(_("Nothing new to pack.\n"));
+		return 0;
+	}
+
+	/* At this point all new packs should be in place. We can
+	   safely remove old ones */
+	for (i = 0; i < backup_files.nr; i++) {
+		const char *s = backup_files.items[i].string;
+		int ret = unlink(s);
+		if (ret)
+			warning("failed to remove %s: %s", s, strerror(errno));
+	}
+	string_list_clear(&backup_files, 0);
+
+	if (repack_flags & REPACK_REMOVE_REDUNDANT) {
+		struct packed_git *p;
+		struct string_list to_be_removed = STRING_LIST_INIT_DUP;
+
+		/* free_pack_by_name() may have freed a few packs in
+		   write_pack_file() */
+		reprepare_packed_git();
+		for (p = packed_git; p; p = p->next) {
+			if (!p->pack_local || p->pack_keep)
+				continue;
+
+			for (i = 0; i < written_packs.nr; i++) {
+				char *s = written_packs.items[i].string;
+				if (!strcmp(s, p->pack_name))
+					break;
+			}
+			if (i < written_packs.nr)
+				continue;
+
+			string_list_append(&to_be_removed, p->pack_name);
+		}
+		written_packs.strdup_strings = 1;
+		string_list_clear(&written_packs, 0);
+
+		for (i = 0; i < to_be_removed.nr; i++) {
+			char *path = to_be_removed.items[i].string;
+
+			/* Windows limitation on unlink().
+			   See c74faea19e39ca933492f697596310397175c329 */
+			free_pack_by_name(path);
+
+			if (unlink(path))
+				warning("failed to remove %s: %s", path, strerror(errno));
+			strcpy(path + strlen(path)-5, ".idx");
+			if (unlink(path))
+				warning("failed to remove %s: %s", path, strerror(errno));
+		}
+		string_list_clear(&to_be_removed, 0);
+
+		reprepare_packed_git();
+		prune_packed_objects(progress ? PRUNE_PACKED_VERBOSE : 0);
+	}
+
+	if (repack_flags & REPACK_UPDATE_INFO)
+		update_server_info(0);
+
 	return 0;
 }
+
+static int repack_config(const char *k, const char *v, void *cb)
+{
+	if (!strcasecmp(k, "repack.usedeltabaseoffset")) {
+		repack_usedeltabaseoffset = git_config_bool(k, v);
+		return 0;
+	}
+	return git_default_config(k, v, cb);
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix)
+{
+	int all_in_one = 0;
+	int all_in_one_and_unreachable = 0;
+	int unpack_unreachable = 0;
+	int remove_redundant = 0;
+	int no_reuse_delta = 0;
+	int no_reuse_object = 0;
+	int no_update = 0;
+	int quiet = 0;
+	int local = 0;
+
+	struct option opts[] = {
+		OPT_BOOL('a', NULL, &all_in_one,
+			 "pack everything in a single pack"),
+		OPT_BOOL('A', NULL, &all_in_one_and_unreachable,
+			 "same as -a, and turn unreachable objects loose"),
+		OPT_BOOL('d', NULL, &remove_redundant,
+			 "remove redundant packs, and run git-prune-packed"),
+		OPT_BOOL('f', NULL, &no_reuse_delta,
+			 "pass --no-reuse-delta to git-pack-objects"),
+		OPT_BOOL('F', NULL, &no_reuse_object,
+			 "pass --no-reuse-object to git-pack-objects"),
+		OPT_BOOL('n', NULL, &no_update,
+			 "do not run git-update-server-info"),
+		OPT_BOOL('q', NULL, &quiet, "be quiet"),
+		OPT_BOOL('l', NULL, &local,
+			 "pass --local to git-pack-objects"),
+		{ OPTION_ARGUMENT, 0, "window", NULL, "n",
+		 "size of the window used for delta compression", 0 },
+		{ OPTION_ARGUMENT, 0, "window-memory", NULL, "n",
+		  "same as the above, but limit memory size instead of entries count", 0 },
+		{ OPTION_ARGUMENT, 0, "depth", NULL, "n",
+		  "limits the maximum delta depth", 0 },
+		{ OPTION_ARGUMENT, 0, "max-pack-size", NULL, "n",
+		  "maximum size of each packfile", 0},
+		OPT_END(),
+	};
+
+	const char *av[] = { "pack-objects", "--repack",
+			     NULL, /* --[no-]update-info */
+			     NULL, /* --delta-base-offset */
+			     NULL, /* --repack-all */
+			     NULL, /* --remove-redundant */
+			     NULL, /* --no-reuse-delta */
+			     NULL, /* --no-reuse-object */
+			     NULL, /* --local */
+			     NULL, /* -q */
+			     NULL, /* --unpack-unreachable */
+			     NULL, /* --window */
+			     NULL, /* --window-memory */
+			     NULL, /* --depth */
+			     NULL, /* --max-pack-size */
+			     NULL
+	};
+	int ac = 2;
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, opts, repack_usage, 0);
+
+	if (no_update)
+		av[ac++] = "--no-update-info";
+	else
+		av[ac++] = "--update-info";
+	if (repack_usedeltabaseoffset)
+		av[ac++] = "--delta-base-offset";
+	if (all_in_one_and_unreachable) {
+		av[ac++] = "--repack-all";
+		all_in_one = 1;
+		unpack_unreachable = 1;
+	}
+	if (all_in_one)
+		av[ac++] = "--repack-all";
+	if (remove_redundant)
+		av[ac++] = "--remove-redundant";
+	if (no_reuse_delta)
+		av[ac++] = "--no-reuse-delta";
+	if (no_reuse_object)
+		av[ac++] = "--no-reuse-object";
+	if (local)
+		av[ac++] = "--local";
+	if (quiet)
+		av[ac++] = "-q";
+	if ((ac + argc) * sizeof(*av) > sizeof(av))
+		die("Too many options");
+	memcpy(av + ac, argv, argc * sizeof(*argv));
+	ac += argc;
+
+	if (all_in_one && remove_redundant) {
+		struct packed_git *p;
+
+		prepare_packed_git();
+		for (p = packed_git; p; p = p->next) {
+			if (!p->pack_keep &&
+			    unpack_unreachable && remove_redundant) {
+				av[ac++] = "--unpack-unreachable";
+				break;
+			}
+		}
+	}
+
+	return cmd_pack_objects(ac, av, prefix);
+}
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 6b0b6d4..3ca3c55 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -46,7 +46,7 @@ static void finish_bulk_checkin(struct bulk_checkin_state *state)
 	sprintf(packname, "%s/pack/pack-", get_object_directory());
 	finish_tmp_packfile(packname, state->pack_tmp_name,
 			    state->written, state->nr_written,
-			    &state->pack_idx_opts, sha1);
+			    &state->pack_idx_opts, sha1, NULL);
 	for (i = 0; i < state->nr_written; i++)
 		free(state->written[i]);
 
diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
similarity index 100%
rename from git-repack.sh
rename to contrib/examples/git-repack.sh
diff --git a/git.c b/git.c
index 1ada169..db4e4b3 100644
--- a/git.c
+++ b/git.c
@@ -389,6 +389,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
 		{ "replace", cmd_replace, RUN_SETUP },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
 		{ "reset", cmd_reset, RUN_SETUP },
diff --git a/pack-write.c b/pack-write.c
index ca9e63b..e6aa7e3 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "pack.h"
 #include "csum-file.h"
+#include "string-list.h"
 
 void reset_pack_idx_option(struct pack_idx_option *opts)
 {
@@ -348,10 +349,12 @@ void finish_tmp_packfile(char *name_buffer,
 			 struct pack_idx_entry **written_list,
 			 uint32_t nr_written,
 			 struct pack_idx_option *pack_idx_opts,
-			 unsigned char sha1[])
+			 unsigned char sha1[],
+			 struct string_list *backup_files)
 {
 	const char *idx_tmp_name;
 	char *end_of_name_prefix = strrchr(name_buffer, 0);
+	struct stat st;
 
 	if (adjust_shared_perm(pack_tmp_name))
 		die_errno("unable to make temporary pack file readable");
@@ -368,6 +371,14 @@ void finish_tmp_packfile(char *name_buffer,
 		die_errno("unable to rename temporary pack file");
 
 	sprintf(end_of_name_prefix, "%s.idx", sha1_to_hex(sha1));
+	if (backup_files && !stat(name_buffer, &st)) {
+		struct strbuf old = STRBUF_INIT;
+		strbuf_addf(&old, "%s.old", name_buffer);
+		if (rename(name_buffer, old.buf))
+			die_errno("unable to rename pack %s", name_buffer);
+		string_list_append(backup_files, strbuf_detach(&old, NULL));
+	}
+	backup_file(name_buffer);
 	if (rename(idx_tmp_name, name_buffer))
 		die_errno("unable to rename temporary index file");
 
diff --git a/pack.h b/pack.h
index aa6ee7d..d3f92ad 100644
--- a/pack.h
+++ b/pack.h
@@ -90,7 +90,9 @@ extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned ch
 #define PH_ERROR_PROTOCOL	(-3)
 extern int read_pack_header(int fd, struct pack_header *);
 
+struct string_list;
+
 extern struct sha1file *create_tmp_packfile(char **pack_tmp_name);
-extern void finish_tmp_packfile(char *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, struct pack_idx_option *pack_idx_opts, unsigned char sha1[]);
+extern void finish_tmp_packfile(char *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, struct pack_idx_option *pack_idx_opts, unsigned char sha1[], struct string_list *backup_files);
 
 #endif
-- 8< --

^ permalink raw reply related	[relevance 1%]

* [PATCHv3 2/9] Replace deprecated OPT_BOOLEAN by OPT_BOOL
  @ 2013-08-03 11:51  3% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-08-03 11:51 UTC (permalink / raw)
  To: git, gitster, sunshine; +Cc: Stefan Beller

This task emerged from b04ba2bb (parse-options: deprecate OPT_BOOLEAN,
2011-09-27). All occurrences of the respective variables have
been reviewed and none of them relied on the counting up mechanism,
but all of them were using the variable as a true boolean.

This patch does not change semantics of any command intentionally.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 builtin/apply.c          | 24 ++++++++++++------------
 builtin/bisect--helper.c |  8 ++++----
 builtin/blame.c          |  8 ++++----
 builtin/branch.c         | 10 +++++-----
 builtin/check-attr.c     |  8 ++++----
 builtin/check-ignore.c   | 12 ++++++------
 builtin/checkout-index.c |  6 +++---
 builtin/checkout.c       | 10 +++++-----
 builtin/clean.c          |  6 +++---
 builtin/clone.c          | 16 ++++++++--------
 builtin/commit.c         | 36 ++++++++++++++++++------------------
 builtin/config.c         |  2 +-
 builtin/describe.c       | 20 ++++++++++----------
 builtin/fast-export.c    | 10 +++++-----
 builtin/fetch.c          | 24 ++++++++++++------------
 builtin/fsck.c           | 16 ++++++++--------
 builtin/gc.c             |  4 ++--
 builtin/grep.c           | 38 +++++++++++++++++++-------------------
 builtin/hash-object.c    |  6 +++---
 builtin/log.c            |  8 ++++----
 builtin/ls-files.c       | 24 ++++++++++++------------
 builtin/ls-tree.c        |  6 +++---
 builtin/merge-base.c     | 10 +++++-----
 builtin/merge-file.c     |  2 +-
 builtin/merge.c          | 12 ++++++------
 builtin/mv.c             |  2 +-
 builtin/name-rev.c       | 12 ++++++------
 builtin/notes.c          |  4 ++--
 builtin/push.c           |  6 +++---
 builtin/remote.c         | 28 ++++++++++++++--------------
 builtin/replace.c        |  6 +++---
 builtin/reset.c          |  2 +-
 builtin/rev-parse.c      |  4 ++--
 builtin/rm.c             |  6 +++---
 builtin/shortlog.c       | 12 ++++++------
 builtin/show-branch.c    | 28 ++++++++++++++--------------
 builtin/show-ref.c       | 10 +++++-----
 builtin/tag.c            |  4 ++--
 builtin/update-ref.c     |  4 ++--
 39 files changed, 227 insertions(+), 227 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 50912c9..ef32e4f 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -4363,23 +4363,23 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 		{ OPTION_CALLBACK, 'p', NULL, NULL, N_("num"),
 			N_("remove <num> leading slashes from traditional diff paths"),
 			0, option_parse_p },
-		OPT_BOOLEAN(0, "no-add", &no_add,
+		OPT_BOOL(0, "no-add", &no_add,
 			N_("ignore additions made by the patch")),
-		OPT_BOOLEAN(0, "stat", &diffstat,
+		OPT_BOOL(0, "stat", &diffstat,
 			N_("instead of applying the patch, output diffstat for the input")),
 		OPT_NOOP_NOARG(0, "allow-binary-replacement"),
 		OPT_NOOP_NOARG(0, "binary"),
-		OPT_BOOLEAN(0, "numstat", &numstat,
+		OPT_BOOL(0, "numstat", &numstat,
 			N_("show number of added and deleted lines in decimal notation")),
-		OPT_BOOLEAN(0, "summary", &summary,
+		OPT_BOOL(0, "summary", &summary,
 			N_("instead of applying the patch, output a summary for the input")),
-		OPT_BOOLEAN(0, "check", &check,
+		OPT_BOOL(0, "check", &check,
 			N_("instead of applying the patch, see if the patch is applicable")),
-		OPT_BOOLEAN(0, "index", &check_index,
+		OPT_BOOL(0, "index", &check_index,
 			N_("make sure the patch is applicable to the current index")),
-		OPT_BOOLEAN(0, "cached", &cached,
+		OPT_BOOL(0, "cached", &cached,
 			N_("apply a patch without touching the working tree")),
-		OPT_BOOLEAN(0, "apply", &force_apply,
+		OPT_BOOL(0, "apply", &force_apply,
 			N_("also apply the patch (use with --stat/--summary/--check)")),
 		OPT_BOOL('3', "3way", &threeway,
 			 N_( "attempt three-way merge if a patch does not apply")),
@@ -4399,13 +4399,13 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 		{ OPTION_CALLBACK, 0, "ignore-whitespace", NULL, NULL,
 			N_("ignore changes in whitespace when finding context"),
 			PARSE_OPT_NOARG, option_parse_space_change },
-		OPT_BOOLEAN('R', "reverse", &apply_in_reverse,
+		OPT_BOOL('R', "reverse", &apply_in_reverse,
 			N_("apply the patch in reverse")),
-		OPT_BOOLEAN(0, "unidiff-zero", &unidiff_zero,
+		OPT_BOOL(0, "unidiff-zero", &unidiff_zero,
 			N_("don't expect at least one line of context")),
-		OPT_BOOLEAN(0, "reject", &apply_with_reject,
+		OPT_BOOL(0, "reject", &apply_with_reject,
 			N_("leave the rejected hunks in corresponding *.rej files")),
-		OPT_BOOLEAN(0, "allow-overlap", &allow_overlap,
+		OPT_BOOL(0, "allow-overlap", &allow_overlap,
 			N_("allow overlapping hunks")),
 		OPT__VERBOSE(&apply_verbosely, N_("be verbose")),
 		OPT_BIT(0, "inaccurate-eof", &options,
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index e3884e3..3324229 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -13,10 +13,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 	int next_all = 0;
 	int no_checkout = 0;
 	struct option options[] = {
-		OPT_BOOLEAN(0, "next-all", &next_all,
-			    N_("perform 'git bisect next'")),
-		OPT_BOOLEAN(0, "no-checkout", &no_checkout,
-			    N_("update BISECT_HEAD instead of checking out the current commit")),
+		OPT_BOOL(0, "next-all", &next_all,
+			 N_("perform 'git bisect next'")),
+		OPT_BOOL(0, "no-checkout", &no_checkout,
+			 N_("update BISECT_HEAD instead of checking out the current commit")),
 		OPT_END()
 	};
 
diff --git a/builtin/blame.c b/builtin/blame.c
index 079dcd3..f932112 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2273,10 +2273,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	static const char *revs_file = NULL;
 	static const char *contents_from = NULL;
 	static const struct option options[] = {
-		OPT_BOOLEAN(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
-		OPT_BOOLEAN('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
-		OPT_BOOLEAN(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
-		OPT_BOOLEAN(0, "show-stats", &show_stats, N_("Show work cost statistics")),
+		OPT_BOOL(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
+		OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
+		OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
+		OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")),
 		OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE),
 		OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME),
 		OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER),
diff --git a/builtin/branch.c b/builtin/branch.c
index 0836890..4daed0b 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -797,7 +797,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT( 0, "set-upstream",  &track, N_("change upstream info"),
 			BRANCH_TRACK_OVERRIDE),
 		OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"),
-		OPT_BOOLEAN(0, "unset-upstream", &unset_upstream, "Unset the upstream info"),
+		OPT_BOOL(0, "unset-upstream", &unset_upstream, "Unset the upstream info"),
 		OPT__COLOR(&branch_use_color, N_("use colored output")),
 		OPT_SET_INT('r', "remotes",     &kinds, N_("act on remote-tracking branches"),
 			REF_REMOTE_BRANCH),
@@ -822,10 +822,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
 		OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
 		OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
-		OPT_BOOLEAN(0, "list", &list, N_("list branch names")),
-		OPT_BOOLEAN('l', "create-reflog", &reflog, N_("create the branch's reflog")),
-		OPT_BOOLEAN(0, "edit-description", &edit_description,
-			    N_("edit the description for the branch")),
+		OPT_BOOL(0, "list", &list, N_("list branch names")),
+		OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
+		OPT_BOOL(0, "edit-description", &edit_description,
+			 N_("edit the description for the branch")),
 		OPT__FORCE(&force_create, N_("force creation (when already exists)")),
 		{
 			OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 075d01d..6e5cd88 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -16,10 +16,10 @@ NULL
 static int null_term_line;
 
 static const struct option check_attr_options[] = {
-	OPT_BOOLEAN('a', "all", &all_attrs, N_("report all attributes set on file")),
-	OPT_BOOLEAN(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
-	OPT_BOOLEAN(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
-	OPT_BOOLEAN('z', NULL, &null_term_line,
+	OPT_BOOL('a', "all", &all_attrs, N_("report all attributes set on file")),
+	OPT_BOOL(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
+	OPT_BOOL(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
+	OPT_BOOL('z', NULL, &null_term_line,
 		N_("input paths are terminated by a null character")),
 	OPT_END()
 };
diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c
index 4a8fc70..c9f0c9b 100644
--- a/builtin/check-ignore.c
+++ b/builtin/check-ignore.c
@@ -18,12 +18,12 @@ static const struct option check_ignore_options[] = {
 	OPT__QUIET(&quiet, N_("suppress progress reporting")),
 	OPT__VERBOSE(&verbose, N_("be verbose")),
 	OPT_GROUP(""),
-	OPT_BOOLEAN(0, "stdin", &stdin_paths,
-		    N_("read file names from stdin")),
-	OPT_BOOLEAN('z', NULL, &null_term_line,
-		    N_("input paths are terminated by a null character")),
-	OPT_BOOLEAN('n', "non-matching", &show_non_matching,
-		    N_("show non-matching input paths")),
+	OPT_BOOL(0, "stdin", &stdin_paths,
+		 N_("read file names from stdin")),
+	OPT_BOOL('z', NULL, &null_term_line,
+		 N_("input paths are terminated by a null character")),
+	OPT_BOOL('n', "non-matching", &show_non_matching,
+		 N_("show non-matching input paths")),
 	OPT_END()
 };
 
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index b1feda7..aa922ed 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -183,7 +183,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 	int prefix_length;
 	int force = 0, quiet = 0, not_new = 0;
 	struct option builtin_checkout_index_options[] = {
-		OPT_BOOLEAN('a', "all", &all,
+		OPT_BOOL('a', "all", &all,
 			N_("check out all files in the index")),
 		OPT__FORCE(&force, N_("force overwrite of existing files")),
 		OPT__QUIET(&quiet,
@@ -196,9 +196,9 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
 			N_("paths are separated with NUL character"),
 			PARSE_OPT_NOARG, option_parse_z },
-		OPT_BOOLEAN(0, "stdin", &read_from_stdin,
+		OPT_BOOL(0, "stdin", &read_from_stdin,
 			N_("read list of paths from the standard input")),
-		OPT_BOOLEAN(0, "temp", &to_tempfile,
+		OPT_BOOL(0, "temp", &to_tempfile,
 			N_("write the content to temporary files")),
 		OPT_CALLBACK(0, "prefix", NULL, N_("string"),
 			N_("when creating files, prepend <string>"),
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 646a475..8b48f4a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1056,8 +1056,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 			   N_("create and checkout a new branch")),
 		OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
 			   N_("create/reset and checkout a branch")),
-		OPT_BOOLEAN('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
-		OPT_BOOLEAN(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
+		OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
+		OPT_BOOL(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
 		OPT_SET_INT('t', "track",  &opts.track, N_("set upstream info for new branch"),
 			BRANCH_TRACK_EXPLICIT),
 		OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new branch"), N_("new unparented branch")),
@@ -1066,11 +1066,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT('3', "theirs", &opts.writeout_stage, N_("checkout their version for unmerged files"),
 			    3),
 		OPT__FORCE(&opts.force, N_("force checkout (throw away local modifications)")),
-		OPT_BOOLEAN('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
-		OPT_BOOLEAN(0, "overwrite-ignore", &opts.overwrite_ignore, N_("update ignored files (default)")),
+		OPT_BOOL('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
+		OPT_BOOL(0, "overwrite-ignore", &opts.overwrite_ignore, N_("update ignored files (default)")),
 		OPT_STRING(0, "conflict", &conflict_style, N_("style"),
 			   N_("conflict style (merge or diff3)")),
-		OPT_BOOLEAN('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
+		OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
 		OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree,
 			 N_("do not limit pathspecs to sparse entries only")),
 		OPT_HIDDEN_BOOL(0, "guess", &dwim_new_local_branch,
diff --git a/builtin/clean.c b/builtin/clean.c
index dba8387..df0f61e 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -851,12 +851,12 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 		OPT__DRY_RUN(&dry_run, N_("dry run")),
 		OPT__FORCE(&force, N_("force")),
 		OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")),
-		OPT_BOOLEAN('d', NULL, &remove_directories,
+		OPT_BOOL('d', NULL, &remove_directories,
 				N_("remove whole directories")),
 		{ OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"),
 		  N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb },
-		OPT_BOOLEAN('x', NULL, &ignored, N_("remove ignored files, too")),
-		OPT_BOOLEAN('X', NULL, &ignored_only,
+		OPT_BOOL('x', NULL, &ignored, N_("remove ignored files, too")),
+		OPT_BOOL('X', NULL, &ignored_only,
 				N_("remove only ignored files")),
 		OPT_END()
 	};
diff --git a/builtin/clone.c b/builtin/clone.c
index e7b0b13..ca3eb68 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -62,22 +62,22 @@ static struct option builtin_clone_options[] = {
 	OPT__VERBOSITY(&option_verbosity),
 	OPT_BOOL(0, "progress", &option_progress,
 		 N_("force progress reporting")),
-	OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
-		    N_("don't create a checkout")),
+	OPT_BOOL('n', "no-checkout", &option_no_checkout,
+		 N_("don't create a checkout")),
 	OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
 	OPT_HIDDEN_BOOL(0, "naked", &option_bare,
 			N_("create a bare repository")),
-	OPT_BOOLEAN(0, "mirror", &option_mirror,
-		    N_("create a mirror repository (implies bare)")),
+	OPT_BOOL(0, "mirror", &option_mirror,
+		 N_("create a mirror repository (implies bare)")),
 	OPT_BOOL('l', "local", &option_local,
 		N_("to clone from a local repository")),
-	OPT_BOOLEAN(0, "no-hardlinks", &option_no_hardlinks,
+	OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
 		    N_("don't use local hardlinks, always copy")),
-	OPT_BOOLEAN('s', "shared", &option_shared,
+	OPT_BOOL('s', "shared", &option_shared,
 		    N_("setup as shared repository")),
-	OPT_BOOLEAN(0, "recursive", &option_recursive,
+	OPT_BOOL(0, "recursive", &option_recursive,
 		    N_("initialize submodules in the clone")),
-	OPT_BOOLEAN(0, "recurse-submodules", &option_recursive,
+	OPT_BOOL(0, "recurse-submodules", &option_recursive,
 		    N_("initialize submodules in the clone")),
 	OPT_STRING(0, "template", &option_template, N_("template-directory"),
 		   N_("directory from which templates will be used")),
diff --git a/builtin/commit.c b/builtin/commit.c
index b64a083..c20426b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1209,14 +1209,14 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT(0, "long", &status_format,
 			    N_("show status in long format (default)"),
 			    STATUS_FORMAT_LONG),
-		OPT_BOOLEAN('z', "null", &s.null_termination,
-			    N_("terminate entries with NUL")),
+		OPT_BOOL('z', "null", &s.null_termination,
+			 N_("terminate entries with NUL")),
 		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
 		  N_("mode"),
 		  N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
 		  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
-		OPT_BOOLEAN(0, "ignored", &show_ignored_in_status,
-			    N_("show ignored files")),
+		OPT_BOOL(0, "ignored", &show_ignored_in_status,
+			 N_("show ignored files")),
 		{ OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
 		  N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
 		  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@ -1415,24 +1415,24 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_STRING('C', "reuse-message", &use_message, N_("commit"), N_("reuse message from specified commit")),
 		OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
 		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
-		OPT_BOOLEAN(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
-		OPT_BOOLEAN('s', "signoff", &signoff, N_("add Signed-off-by:")),
+		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
+		OPT_BOOL('s', "signoff", &signoff, N_("add Signed-off-by:")),
 		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
 		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
 		OPT_STRING(0, "cleanup", &cleanup_arg, N_("default"), N_("how to strip spaces and #comments from message")),
-		OPT_BOOLEAN(0, "status", &include_status, N_("include status in commit message template")),
+		OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")),
 		{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
 		  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 		/* end commit message options */
 
 		OPT_GROUP(N_("Commit contents options")),
-		OPT_BOOLEAN('a', "all", &all, N_("commit all changed files")),
-		OPT_BOOLEAN('i', "include", &also, N_("add specified files to index for commit")),
-		OPT_BOOLEAN(0, "interactive", &interactive, N_("interactively add files")),
-		OPT_BOOLEAN('p', "patch", &patch_interactive, N_("interactively add changes")),
-		OPT_BOOLEAN('o', "only", &only, N_("commit only specified files")),
-		OPT_BOOLEAN('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
-		OPT_BOOLEAN(0, "dry-run", &dry_run, N_("show what would be committed")),
+		OPT_BOOL('a', "all", &all, N_("commit all changed files")),
+		OPT_BOOL('i', "include", &also, N_("add specified files to index for commit")),
+		OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
+		OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
+		OPT_BOOL('o', "only", &only, N_("commit only specified files")),
+		OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
+		OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
 		OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
 			    STATUS_FORMAT_SHORT),
 		OPT_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
@@ -1441,10 +1441,10 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT(0, "long", &status_format,
 			    N_("show status in long format (default)"),
 			    STATUS_FORMAT_LONG),
-		OPT_BOOLEAN('z', "null", &s.null_termination,
-			    N_("terminate entries with NUL")),
-		OPT_BOOLEAN(0, "amend", &amend, N_("amend previous commit")),
-		OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
+		OPT_BOOL('z', "null", &s.null_termination,
+			 N_("terminate entries with NUL")),
+		OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
+		OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
 		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
 		/* end commit contents options */
 
diff --git a/builtin/config.c b/builtin/config.c
index 4010c43..da12fdb 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -75,7 +75,7 @@ static struct option builtin_config_options[] = {
 	OPT_BIT(0, "bool-or-int", &types, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
 	OPT_BIT(0, "path", &types, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOLEAN('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")),
 	OPT_END(),
 };
diff --git a/builtin/describe.c b/builtin/describe.c
index 7d73722..c94e5c3 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -406,12 +406,12 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 {
 	int contains = 0;
 	struct option options[] = {
-		OPT_BOOLEAN(0, "contains",   &contains, N_("find the tag that comes after the commit")),
-		OPT_BOOLEAN(0, "debug",      &debug, N_("debug search strategy on stderr")),
-		OPT_BOOLEAN(0, "all",        &all, N_("use any ref")),
-		OPT_BOOLEAN(0, "tags",       &tags, N_("use any tag, even unannotated")),
-		OPT_BOOLEAN(0, "long",       &longformat, N_("always use long format")),
-		OPT_BOOLEAN(0, "first-parent", &first_parent, N_("only follow first parent")),
+		OPT_BOOL(0, "contains",   &contains, N_("find the tag that comes after the commit")),
+		OPT_BOOL(0, "debug",      &debug, N_("debug search strategy on stderr")),
+		OPT_BOOL(0, "all",        &all, N_("use any ref")),
+		OPT_BOOL(0, "tags",       &tags, N_("use any tag, even unannotated")),
+		OPT_BOOL(0, "long",       &longformat, N_("always use long format")),
+		OPT_BOOL(0, "first-parent", &first_parent, N_("only follow first parent")),
 		OPT__ABBREV(&abbrev),
 		OPT_SET_INT(0, "exact-match", &max_candidates,
 			    N_("only output exact matches"), 0),
@@ -419,11 +419,11 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 			    N_("consider <n> most recent tags (default: 10)")),
 		OPT_STRING(0, "match",       &pattern, N_("pattern"),
 			   N_("only consider tags matching <pattern>")),
-		OPT_BOOLEAN(0, "always",     &always,
-			   N_("show abbreviated commit object as fallback")),
+		OPT_BOOL(0, "always",        &always,
+			N_("show abbreviated commit object as fallback")),
 		{OPTION_STRING, 0, "dirty",  &dirty, N_("mark"),
-			   N_("append <mark> on dirty working tree (default: \"-dirty\")"),
-		 PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
+			N_("append <mark> on dirty working tree (default: \"-dirty\")"),
+			PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
 		OPT_END(),
 	};
 
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index d1d68e9..32b0c3f 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -674,11 +674,11 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 			     N_("Dump marks to this file")),
 		OPT_STRING(0, "import-marks", &import_filename, N_("file"),
 			     N_("Import marks from this file")),
-		OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
-			     N_("Fake a tagger when tags lack one")),
-		OPT_BOOLEAN(0, "full-tree", &full_tree,
-			     N_("Output full tree for each commit")),
-		OPT_BOOLEAN(0, "use-done-feature", &use_done_feature,
+		OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
+			 N_("Fake a tagger when tags lack one")),
+		OPT_BOOL(0, "full-tree", &full_tree,
+			 N_("Output full tree for each commit")),
+		OPT_BOOL(0, "use-done-feature", &use_done_feature,
 			     N_("Use the done feature to terminate the stream")),
 		OPT_BOOL(0, "no-data", &no_data, N_("Skip output of blob data")),
 		OPT_END()
diff --git a/builtin/fetch.c b/builtin/fetch.c
index d784b2e..99afed0 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -56,28 +56,28 @@ static int option_parse_recurse_submodules(const struct option *opt,
 
 static struct option builtin_fetch_options[] = {
 	OPT__VERBOSITY(&verbosity),
-	OPT_BOOLEAN(0, "all", &all,
-		    N_("fetch from all remotes")),
-	OPT_BOOLEAN('a', "append", &append,
-		    N_("append to .git/FETCH_HEAD instead of overwriting")),
+	OPT_BOOL(0, "all", &all,
+		 N_("fetch from all remotes")),
+	OPT_BOOL('a', "append", &append,
+		 N_("append to .git/FETCH_HEAD instead of overwriting")),
 	OPT_STRING(0, "upload-pack", &upload_pack, N_("path"),
 		   N_("path to upload pack on remote end")),
 	OPT__FORCE(&force, N_("force overwrite of local branch")),
-	OPT_BOOLEAN('m', "multiple", &multiple,
-		    N_("fetch from multiple remotes")),
+	OPT_BOOL('m', "multiple", &multiple,
+		 N_("fetch from multiple remotes")),
 	OPT_SET_INT('t', "tags", &tags,
 		    N_("fetch all tags and associated objects"), TAGS_SET),
 	OPT_SET_INT('n', NULL, &tags,
 		    N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
-	OPT_BOOLEAN('p', "prune", &prune,
-		    N_("prune remote-tracking branches no longer on remote")),
+	OPT_BOOL('p', "prune", &prune,
+		 N_("prune remote-tracking branches no longer on remote")),
 	{ OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
 		    N_("control recursive fetching of submodules"),
 		    PARSE_OPT_OPTARG, option_parse_recurse_submodules },
-	OPT_BOOLEAN(0, "dry-run", &dry_run,
-		    N_("dry run")),
-	OPT_BOOLEAN('k', "keep", &keep, N_("keep downloaded pack")),
-	OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
+	OPT_BOOL(0, "dry-run", &dry_run,
+		 N_("dry run")),
+	OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
+	OPT_BOOL('u', "update-head-ok", &update_head_ok,
 		    N_("allow updating of HEAD ref")),
 	OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
 	OPT_STRING(0, "depth", &depth, N_("depth"),
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 9909b6d..39fa5e8 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -611,15 +611,15 @@ static char const * const fsck_usage[] = {
 
 static struct option fsck_opts[] = {
 	OPT__VERBOSE(&verbose, N_("be verbose")),
-	OPT_BOOLEAN(0, "unreachable", &show_unreachable, N_("show unreachable objects")),
+	OPT_BOOL(0, "unreachable", &show_unreachable, N_("show unreachable objects")),
 	OPT_BOOL(0, "dangling", &show_dangling, N_("show dangling objects")),
-	OPT_BOOLEAN(0, "tags", &show_tags, N_("report tags")),
-	OPT_BOOLEAN(0, "root", &show_root, N_("report root nodes")),
-	OPT_BOOLEAN(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
-	OPT_BOOLEAN(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
-	OPT_BOOLEAN(0, "full", &check_full, N_("also consider packs and alternate objects")),
-	OPT_BOOLEAN(0, "strict", &check_strict, N_("enable more strict checking")),
-	OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
+	OPT_BOOL(0, "tags", &show_tags, N_("report tags")),
+	OPT_BOOL(0, "root", &show_root, N_("report root nodes")),
+	OPT_BOOL(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
+	OPT_BOOL(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
+	OPT_BOOL(0, "full", &check_full, N_("also consider packs and alternate objects")),
+	OPT_BOOL(0, "strict", &check_strict, N_("enable more strict checking")),
+	OPT_BOOL(0, "lost-found", &write_lost_and_found,
 				N_("write dangling objects in .git/lost-found")),
 	OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
 	OPT_END(),
diff --git a/builtin/gc.c b/builtin/gc.c
index 6be6c8d..c4f7390 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -178,8 +178,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 		{ OPTION_STRING, 0, "prune", &prune_expire, N_("date"),
 			N_("prune unreferenced objects"),
 			PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
-		OPT_BOOLEAN(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
-		OPT_BOOLEAN(0, "auto", &auto_gc, N_("enable auto-gc mode")),
+		OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
+		OPT_BOOL(0, "auto", &auto_gc, N_("enable auto-gc mode")),
 		OPT_END()
 	};
 
diff --git a/builtin/grep.c b/builtin/grep.c
index d3b3b1d..7877e77 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -638,20 +638,20 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	int pattern_type_arg = GREP_PATTERN_TYPE_UNSPECIFIED;
 
 	struct option options[] = {
-		OPT_BOOLEAN(0, "cached", &cached,
+		OPT_BOOL(0, "cached", &cached,
 			N_("search in index instead of in the work tree")),
 		OPT_NEGBIT(0, "no-index", &use_index,
 			 N_("find in contents not managed by git"), 1),
-		OPT_BOOLEAN(0, "untracked", &untracked,
+		OPT_BOOL(0, "untracked", &untracked,
 			N_("search in both tracked and untracked files")),
 		OPT_SET_INT(0, "exclude-standard", &opt_exclude,
 			    N_("search also in ignored files"), 1),
 		OPT_GROUP(""),
-		OPT_BOOLEAN('v', "invert-match", &opt.invert,
+		OPT_BOOL('v', "invert-match", &opt.invert,
 			N_("show non-matching lines")),
-		OPT_BOOLEAN('i', "ignore-case", &opt.ignore_case,
+		OPT_BOOL('i', "ignore-case", &opt.ignore_case,
 			N_("case insensitive matching")),
-		OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
+		OPT_BOOL('w', "word-regexp", &opt.word_regexp,
 			N_("match patterns only at word boundaries")),
 		OPT_SET_INT('a', "text", &opt.binary,
 			N_("process binary files as text"), GREP_BINARY_TEXT),
@@ -675,26 +675,26 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 			    N_("use Perl-compatible regular expressions"),
 			    GREP_PATTERN_TYPE_PCRE),
 		OPT_GROUP(""),
-		OPT_BOOLEAN('n', "line-number", &opt.linenum, N_("show line numbers")),
+		OPT_BOOL('n', "line-number", &opt.linenum, N_("show line numbers")),
 		OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show filenames"), 1),
 		OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1),
 		OPT_NEGBIT(0, "full-name", &opt.relative,
 			N_("show filenames relative to top directory"), 1),
-		OPT_BOOLEAN('l', "files-with-matches", &opt.name_only,
+		OPT_BOOL('l', "files-with-matches", &opt.name_only,
 			N_("show only filenames instead of matching lines")),
-		OPT_BOOLEAN(0, "name-only", &opt.name_only,
+		OPT_BOOL(0, "name-only", &opt.name_only,
 			N_("synonym for --files-with-matches")),
-		OPT_BOOLEAN('L', "files-without-match",
+		OPT_BOOL('L', "files-without-match",
 			&opt.unmatch_name_only,
 			N_("show only the names of files without match")),
-		OPT_BOOLEAN('z', "null", &opt.null_following_name,
+		OPT_BOOL('z', "null", &opt.null_following_name,
 			N_("print NUL after filenames")),
-		OPT_BOOLEAN('c', "count", &opt.count,
+		OPT_BOOL('c', "count", &opt.count,
 			N_("show the number of matches instead of matching lines")),
 		OPT__COLOR(&opt.color, N_("highlight matches")),
-		OPT_BOOLEAN(0, "break", &opt.file_break,
+		OPT_BOOL(0, "break", &opt.file_break,
 			N_("print empty line between matches from different files")),
-		OPT_BOOLEAN(0, "heading", &opt.heading,
+		OPT_BOOL(0, "heading", &opt.heading,
 			N_("show filename only once above matches from same file")),
 		OPT_GROUP(""),
 		OPT_CALLBACK('C', "context", &opt, N_("n"),
@@ -706,9 +706,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 			N_("show <n> context lines after matches")),
 		OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
 			context_callback),
-		OPT_BOOLEAN('p', "show-function", &opt.funcname,
+		OPT_BOOL('p', "show-function", &opt.funcname,
 			N_("show a line with the function name before matches")),
-		OPT_BOOLEAN('W', "function-context", &opt.funcbody,
+		OPT_BOOL('W', "function-context", &opt.funcbody,
 			N_("show the surrounding function")),
 		OPT_GROUP(""),
 		OPT_CALLBACK('f', NULL, &opt, N_("file"),
@@ -718,7 +718,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 0, "and", &opt, NULL,
 		  N_("combine patterns specified with -e"),
 		  PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
-		OPT_BOOLEAN(0, "or", &dummy, ""),
+		OPT_BOOL(0, "or", &dummy, ""),
 		{ OPTION_CALLBACK, 0, "not", &opt, NULL, "",
 		  PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
 		{ OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
@@ -729,7 +729,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		  close_callback },
 		OPT__QUIET(&opt.status_only,
 			   N_("indicate hit with exit status without output")),
-		OPT_BOOLEAN(0, "all-match", &opt.all_match,
+		OPT_BOOL(0, "all-match", &opt.all_match,
 			N_("show only matches from files that match all patterns")),
 		{ OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
 		  N_("show parse tree for grep expression"),
@@ -738,8 +738,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		{ OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
 			N_("pager"), N_("show matching files in the pager"),
 			PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
-		OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed__ignored,
-			    N_("allow calling of grep(1) (ignored by this build)")),
+		OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored,
+			 N_("allow calling of grep(1) (ignored by this build)")),
 		{ OPTION_CALLBACK, 0, "help-all", &options, NULL, N_("show usage"),
 		  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
 		OPT_END()
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 8d184f1..4aea5bb 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -70,10 +70,10 @@ static const char *vpath;
 
 static const struct option hash_object_options[] = {
 	OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
-	OPT_BOOLEAN('w', NULL, &write_object, N_("write the object into the object database")),
+	OPT_BOOL('w', NULL, &write_object, N_("write the object into the object database")),
 	OPT_BOOLEAN( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
-	OPT_BOOLEAN( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
-	OPT_BOOLEAN( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
+	OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
+	OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
 	OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")),
 	OPT_END()
 };
diff --git a/builtin/log.c b/builtin/log.c
index 05e374d..1dafbd0 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1179,10 +1179,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
 			    N_("don't strip/add [PATCH]"),
 			    PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
-		OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
-			    N_("don't output binary diffs")),
-		OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
-			    N_("don't include a patch matching a commit upstream")),
+		OPT_BOOL(0, "no-binary", &no_binary_diff,
+			 N_("don't output binary diffs")),
+		OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
+			 N_("don't include a patch matching a commit upstream")),
 		{ OPTION_SET_INT, 'p', "no-stat", &use_patch_format, NULL,
 		  N_("show patch format instead of default (patch + stat)"),
 		  PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1},
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 5cf3e31..963ccc9 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -461,24 +461,24 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
 			N_("paths are separated with NUL character"),
 			PARSE_OPT_NOARG, option_parse_z },
-		OPT_BOOLEAN('t', NULL, &show_tag,
+		OPT_BOOL('t', NULL, &show_tag,
 			N_("identify the file status with tags")),
-		OPT_BOOLEAN('v', NULL, &show_valid_bit,
+		OPT_BOOL('v', NULL, &show_valid_bit,
 			N_("use lowercase letters for 'assume unchanged' files")),
-		OPT_BOOLEAN('c', "cached", &show_cached,
+		OPT_BOOL('c', "cached", &show_cached,
 			N_("show cached files in the output (default)")),
-		OPT_BOOLEAN('d', "deleted", &show_deleted,
+		OPT_BOOL('d', "deleted", &show_deleted,
 			N_("show deleted files in the output")),
-		OPT_BOOLEAN('m', "modified", &show_modified,
+		OPT_BOOL('m', "modified", &show_modified,
 			N_("show modified files in the output")),
-		OPT_BOOLEAN('o', "others", &show_others,
+		OPT_BOOL('o', "others", &show_others,
 			N_("show other files in the output")),
 		OPT_BIT('i', "ignored", &dir.flags,
 			N_("show ignored files in the output"),
 			DIR_SHOW_IGNORED),
-		OPT_BOOLEAN('s', "stage", &show_stage,
+		OPT_BOOL('s', "stage", &show_stage,
 			N_("show staged contents' object name in the output")),
-		OPT_BOOLEAN('k', "killed", &show_killed,
+		OPT_BOOL('k', "killed", &show_killed,
 			N_("show files on the filesystem that need to be removed")),
 		OPT_BIT(0, "directory", &dir.flags,
 			N_("show 'other' directories' name only"),
@@ -486,9 +486,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		OPT_NEGBIT(0, "empty-directory", &dir.flags,
 			N_("don't show empty directories"),
 			DIR_HIDE_EMPTY_DIRECTORIES),
-		OPT_BOOLEAN('u', "unmerged", &show_unmerged,
+		OPT_BOOL('u', "unmerged", &show_unmerged,
 			N_("show unmerged files in the output")),
-		OPT_BOOLEAN(0, "resolve-undo", &show_resolve_undo,
+		OPT_BOOL(0, "resolve-undo", &show_resolve_undo,
 			    N_("show resolve-undo information")),
 		{ OPTION_CALLBACK, 'x', "exclude", &exclude_list, N_("pattern"),
 			N_("skip files matching pattern"),
@@ -504,12 +504,12 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		{ OPTION_SET_INT, 0, "full-name", &prefix_len, NULL,
 			N_("make the output relative to the project top directory"),
 			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
-		OPT_BOOLEAN(0, "error-unmatch", &error_unmatch,
+		OPT_BOOL(0, "error-unmatch", &error_unmatch,
 			N_("if any <file> is not in the index, treat this as an error")),
 		OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
 			N_("pretend that paths removed since <tree-ish> are still present")),
 		OPT__ABBREV(&abbrev),
-		OPT_BOOLEAN(0, "debug", &debug_mode, N_("show debugging data")),
+		OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
 		OPT_END()
 	};
 
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index fb76e38..de88563 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -138,9 +138,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 			LS_NAME_ONLY),
 		OPT_SET_INT(0, "full-name", &chomp_prefix,
 			    N_("use full path names"), 0),
-		OPT_BOOLEAN(0, "full-tree", &full_tree,
-			    N_("list entire tree; not just current directory "
-			       "(implies --full-name)")),
+		OPT_BOOL(0, "full-tree", &full_tree,
+			 N_("list entire tree; not just current directory "
+			    "(implies --full-name)")),
 		OPT__ABBREV(&abbrev),
 		OPT_END()
 	};
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 0c4cd2f..e88eb93 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -95,11 +95,11 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
 	int is_ancestor = 0;
 
 	struct option options[] = {
-		OPT_BOOLEAN('a', "all", &show_all, N_("output all common ancestors")),
-		OPT_BOOLEAN(0, "octopus", &octopus, N_("find ancestors for a single n-way merge")),
-		OPT_BOOLEAN(0, "independent", &reduce, N_("list revs not reachable from others")),
-		OPT_BOOLEAN(0, "is-ancestor", &is_ancestor,
-			    N_("is the first one ancestor of the other?")),
+		OPT_BOOL('a', "all", &show_all, N_("output all common ancestors")),
+		OPT_BOOL(0, "octopus", &octopus, N_("find ancestors for a single n-way merge")),
+		OPT_BOOL(0, "independent", &reduce, N_("list revs not reachable from others")),
+		OPT_BOOL(0, "is-ancestor", &is_ancestor,
+			 N_("is the first one ancestor of the other?")),
 		OPT_END()
 	};
 
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index c0570f2..844f84f 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -30,7 +30,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 	int quiet = 0;
 	int prefixlen = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('p', "stdout", &to_stdout, N_("send results to standard output")),
+		OPT_BOOL('p', "stdout", &to_stdout, N_("send results to standard output")),
 		OPT_SET_INT(0, "diff3", &xmp.style, N_("use a diff3 based merge"), XDL_MERGE_DIFF3),
 		OPT_SET_INT(0, "ours", &xmp.favor, N_("for conflicts, use our version"),
 			    XDL_MERGE_FAVOR_OURS),
diff --git a/builtin/merge.c b/builtin/merge.c
index 34a6166..a8cf4a2 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -197,15 +197,15 @@ static struct option builtin_merge_options[] = {
 	{ OPTION_CALLBACK, 'n', NULL, NULL, NULL,
 		N_("do not show a diffstat at the end of the merge"),
 		PARSE_OPT_NOARG, option_parse_n },
-	OPT_BOOLEAN(0, "stat", &show_diffstat,
+	OPT_BOOL(0, "stat", &show_diffstat,
 		N_("show a diffstat at the end of the merge")),
-	OPT_BOOLEAN(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
+	OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
 	{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
 	  N_("add (at most <n>) entries from shortlog to merge commit message"),
 	  PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
-	OPT_BOOLEAN(0, "squash", &squash,
+	OPT_BOOL(0, "squash", &squash,
 		N_("create a single commit instead of doing a merge")),
-	OPT_BOOLEAN(0, "commit", &option_commit,
+	OPT_BOOL(0, "commit", &option_commit,
 		N_("perform a commit if the merge succeeds (default)")),
 	OPT_BOOL('e', "edit", &option_edit,
 		N_("edit message before committing")),
@@ -224,12 +224,12 @@ static struct option builtin_merge_options[] = {
 		N_("merge commit message (for a non-fast-forward merge)"),
 		option_parse_message),
 	OPT__VERBOSITY(&verbosity),
-	OPT_BOOLEAN(0, "abort", &abort_current_merge,
+	OPT_BOOL(0, "abort", &abort_current_merge,
 		N_("abort the current in-progress merge")),
 	OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
 	{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
 	  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-	OPT_BOOLEAN(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
+	OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
 	OPT_END()
 };
 
diff --git a/builtin/mv.c b/builtin/mv.c
index 034fec9..be6fa77 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -62,7 +62,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 		OPT__VERBOSE(&verbose, N_("be verbose")),
 		OPT__DRY_RUN(&show_only, N_("dry run")),
 		OPT__FORCE(&force, N_("force move/rename even if target exists")),
-		OPT_BOOLEAN('k', NULL, &ignore_errors, N_("skip move/rename errors")),
+		OPT_BOOL('k', NULL, &ignore_errors, N_("skip move/rename errors")),
 		OPT_END(),
 	};
 	const char **source, **destination, **dest_path;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 0aaa19e..a908a34 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -310,15 +310,15 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 	int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
 	struct name_ref_data data = { 0, 0, NULL };
 	struct option opts[] = {
-		OPT_BOOLEAN(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
-		OPT_BOOLEAN(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
+		OPT_BOOL(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
+		OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
 		OPT_STRING(0, "refs", &data.ref_filter, N_("pattern"),
 				   N_("only use refs matching <pattern>")),
 		OPT_GROUP(""),
-		OPT_BOOLEAN(0, "all", &all, N_("list all commits reachable from all refs")),
-		OPT_BOOLEAN(0, "stdin", &transform_stdin, N_("read from stdin")),
-		OPT_BOOLEAN(0, "undefined", &allow_undefined, N_("allow to print `undefined` names")),
-		OPT_BOOLEAN(0, "always",     &always,
+		OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
+		OPT_BOOL(0, "stdin", &transform_stdin, N_("read from stdin")),
+		OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
+		OPT_BOOL(0, "always",     &always,
 			   N_("show abbreviated commit object as fallback")),
 		{
 			/* A Hidden OPT_BOOL */
diff --git a/builtin/notes.c b/builtin/notes.c
index 8f63cb2..d459e23 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -483,7 +483,7 @@ static int copy(int argc, const char **argv, const char *prefix)
 	const char *rewrite_cmd = NULL;
 	struct option options[] = {
 		OPT__FORCE(&force, N_("replace existing notes")),
-		OPT_BOOLEAN(0, "stdin", &from_stdin, N_("read objects from stdin")),
+		OPT_BOOL(0, "stdin", &from_stdin, N_("read objects from stdin")),
 		OPT_STRING(0, "for-rewrite", &rewrite_cmd, N_("command"),
 			   N_("load rewriting config for <command> (implies "
 			      "--stdin)")),
@@ -853,7 +853,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
 		OPT_BIT(0, "ignore-missing", &flag,
 			N_("attempt to remove non-existent note is not an error"),
 			IGNORE_MISSING),
-		OPT_BOOLEAN(0, "stdin", &from_stdin,
+		OPT_BOOL(0, "stdin", &from_stdin,
 			    N_("read object names from the standard input")),
 		OPT_END()
 	};
diff --git a/builtin/push.c b/builtin/push.c
index 6d36c24..bebaf3d 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -446,15 +446,15 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
 		OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
 			    (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
-		OPT_BOOLEAN( 0, "delete", &deleterefs, N_("delete refs")),
-		OPT_BOOLEAN( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
+		OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")),
+		OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
 		OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
 		OPT_BIT( 0,  "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
 		OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
 		{ OPTION_CALLBACK, 0, "recurse-submodules", &flags, N_("check"),
 			N_("control recursive pushing of submodules"),
 			PARSE_OPT_OPTARG, option_parse_recurse_submodules },
-		OPT_BOOLEAN( 0 , "thin", &thin, N_("use thin pack")),
+		OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")),
 		OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
 		OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
 		OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
diff --git a/builtin/remote.c b/builtin/remote.c
index 5e54d36..eaac3e2 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -160,7 +160,7 @@ static int add(int argc, const char **argv)
 	int i;
 
 	struct option options[] = {
-		OPT_BOOLEAN('f', "fetch", &fetch, N_("fetch the remote branches")),
+		OPT_BOOL('f', "fetch", &fetch, N_("fetch the remote branches")),
 		OPT_SET_INT(0, "tags", &fetch_tags,
 			    N_("import all tags and associated objects when fetching"),
 			    TAGS_SET),
@@ -1088,7 +1088,7 @@ static int show(int argc, const char **argv)
 {
 	int no_query = 0, result = 0, query_flag = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('n', NULL, &no_query, N_("do not query remotes")),
+		OPT_BOOL('n', NULL, &no_query, N_("do not query remotes")),
 		OPT_END()
 	};
 	struct ref_states states;
@@ -1195,10 +1195,10 @@ static int set_head(int argc, const char **argv)
 	char *head_name = NULL;
 
 	struct option options[] = {
-		OPT_BOOLEAN('a', "auto", &opt_a,
-			    N_("set refs/remotes/<name>/HEAD according to remote")),
-		OPT_BOOLEAN('d', "delete", &opt_d,
-			    N_("delete refs/remotes/<name>/HEAD")),
+		OPT_BOOL('a', "auto", &opt_a,
+			 N_("set refs/remotes/<name>/HEAD according to remote")),
+		OPT_BOOL('d', "delete", &opt_d,
+			 N_("delete refs/remotes/<name>/HEAD")),
 		OPT_END()
 	};
 	argc = parse_options(argc, argv, NULL, options, builtin_remote_sethead_usage,
@@ -1317,8 +1317,8 @@ static int update(int argc, const char **argv)
 {
 	int i, prune = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('p', "prune", &prune,
-			    N_("prune remotes after fetching")),
+		OPT_BOOL('p', "prune", &prune,
+			 N_("prune remotes after fetching")),
 		OPT_END()
 	};
 	const char **fetch_argv;
@@ -1404,7 +1404,7 @@ static int set_branches(int argc, const char **argv)
 {
 	int add_mode = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('\0', "add", &add_mode, N_("add branch")),
+		OPT_BOOL('\0', "add", &add_mode, N_("add branch")),
 		OPT_END()
 	};
 
@@ -1432,11 +1432,11 @@ static int set_url(int argc, const char **argv)
 	int urlset_nr;
 	struct strbuf name_buf = STRBUF_INIT;
 	struct option options[] = {
-		OPT_BOOLEAN('\0', "push", &push_mode,
-			    N_("manipulate push URLs")),
-		OPT_BOOLEAN('\0', "add", &add_mode,
-			    N_("add URL")),
-		OPT_BOOLEAN('\0', "delete", &delete_mode,
+		OPT_BOOL('\0', "push", &push_mode,
+			 N_("manipulate push URLs")),
+		OPT_BOOL('\0', "add", &add_mode,
+			 N_("add URL")),
+		OPT_BOOL('\0', "delete", &delete_mode,
 			    N_("delete URLs")),
 		OPT_END()
 	};
diff --git a/builtin/replace.c b/builtin/replace.c
index 59d3115..11b0a55 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -118,9 +118,9 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
 {
 	int list = 0, delete = 0, force = 0;
 	struct option options[] = {
-		OPT_BOOLEAN('l', NULL, &list, N_("list replace refs")),
-		OPT_BOOLEAN('d', NULL, &delete, N_("delete replace refs")),
-		OPT_BOOLEAN('f', NULL, &force, N_("replace the ref if it exists")),
+		OPT_BOOL('l', NULL, &list, N_("list replace refs")),
+		OPT_BOOL('d', NULL, &delete, N_("delete replace refs")),
+		OPT_BOOL('f', NULL, &force, N_("replace the ref if it exists")),
 		OPT_END()
 	};
 
diff --git a/builtin/reset.c b/builtin/reset.c
index afa6e02..0905815 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -258,7 +258,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				N_("reset HEAD, index and working tree"), MERGE),
 		OPT_SET_INT(0, "keep", &reset_type,
 				N_("reset HEAD but keep local changes"), KEEP),
-		OPT_BOOLEAN('p', "patch", &patch_mode, N_("select hunks interactively")),
+		OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
 		OPT_END()
 	};
 
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index de894c7..67e8ccf 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -346,9 +346,9 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 		NULL
 	};
 	static struct option parseopt_opts[] = {
-		OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
+		OPT_BOOL(0, "keep-dashdash", &keep_dashdash,
 					N_("keep the `--` passed as an arg")),
-		OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option,
+		OPT_BOOL(0, "stop-at-non-option", &stop_at_non_option,
 					N_("stop parsing after the "
 					   "first non-option argument")),
 		OPT_END(),
diff --git a/builtin/rm.c b/builtin/rm.c
index 18916e0..ce28fa9 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -268,10 +268,10 @@ static int ignore_unmatch = 0;
 static struct option builtin_rm_options[] = {
 	OPT__DRY_RUN(&show_only, N_("dry run")),
 	OPT__QUIET(&quiet, N_("do not list removed files")),
-	OPT_BOOLEAN( 0 , "cached",         &index_only, N_("only remove from the index")),
+	OPT_BOOL( 0 , "cached",         &index_only, N_("only remove from the index")),
 	OPT__FORCE(&force, N_("override the up-to-date check")),
-	OPT_BOOLEAN('r', NULL,             &recursive,  N_("allow recursive removal")),
-	OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
+	OPT_BOOL('r', NULL,             &recursive,  N_("allow recursive removal")),
+	OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch,
 				N_("exit with a zero status even if nothing matched")),
 	OPT_END(),
 };
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 1434f8f..ae73d17 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -224,12 +224,12 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
 	int nongit = !startup_info->have_repository;
 
 	static const struct option options[] = {
-		OPT_BOOLEAN('n', "numbered", &log.sort_by_number,
-			    N_("sort output according to the number of commits per author")),
-		OPT_BOOLEAN('s', "summary", &log.summary,
-			    N_("Suppress commit descriptions, only provides commit count")),
-		OPT_BOOLEAN('e', "email", &log.email,
-			    N_("Show the email address of each author")),
+		OPT_BOOL('n', "numbered", &log.sort_by_number,
+			 N_("sort output according to the number of commits per author")),
+		OPT_BOOL('s', "summary", &log.summary,
+			 N_("Suppress commit descriptions, only provides commit count")),
+		OPT_BOOL('e', "email", &log.email,
+			 N_("Show the email address of each author")),
 		{ OPTION_CALLBACK, 'w', NULL, &log, N_("w[,i1[,i2]]"),
 			N_("Linewrap output"), PARSE_OPT_OPTARG, &parse_wrap_args },
 		OPT_END(),
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 9788eb1..001f29c 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -646,30 +646,30 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 	int dense = 1;
 	const char *reflog_base = NULL;
 	struct option builtin_show_branch_options[] = {
-		OPT_BOOLEAN('a', "all", &all_heads,
-			    N_("show remote-tracking and local branches")),
-		OPT_BOOLEAN('r', "remotes", &all_remotes,
-			    N_("show remote-tracking branches")),
+		OPT_BOOL('a', "all", &all_heads,
+			 N_("show remote-tracking and local branches")),
+		OPT_BOOL('r', "remotes", &all_remotes,
+			 N_("show remote-tracking branches")),
 		OPT__COLOR(&showbranch_use_color,
 			    N_("color '*!+-' corresponding to the branch")),
 		{ OPTION_INTEGER, 0, "more", &extra, N_("n"),
 			    N_("show <n> more commits after the common ancestor"),
 			    PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
 		OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1),
-		OPT_BOOLEAN(0, "no-name", &no_name, N_("suppress naming strings")),
-		OPT_BOOLEAN(0, "current", &with_current_branch,
-			    N_("include the current branch")),
-		OPT_BOOLEAN(0, "sha1-name", &sha1_name,
-			    N_("name commits with their object names")),
-		OPT_BOOLEAN(0, "merge-base", &merge_base,
-			    N_("show possible merge bases")),
-		OPT_BOOLEAN(0, "independent", &independent,
+		OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")),
+		OPT_BOOL(0, "current", &with_current_branch,
+			 N_("include the current branch")),
+		OPT_BOOL(0, "sha1-name", &sha1_name,
+			 N_("name commits with their object names")),
+		OPT_BOOL(0, "merge-base", &merge_base,
+			 N_("show possible merge bases")),
+		OPT_BOOL(0, "independent", &independent,
 			    N_("show refs unreachable from any other ref")),
 		OPT_SET_INT(0, "topo-order", &sort_order,
 			    N_("show commits in topological order"),
 			    REV_SORT_IN_GRAPH_ORDER),
-		OPT_BOOLEAN(0, "topics", &topics,
-			    N_("show only commits not on the first branch")),
+		OPT_BOOL(0, "topics", &topics,
+			 N_("show only commits not on the first branch")),
 		OPT_SET_INT(0, "sparse", &dense,
 			    N_("show merges reachable from only one tip"), 0),
 		OPT_SET_INT(0, "date-order", &sort_order,
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 18680bb..9f3f5e3 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -165,15 +165,15 @@ static int help_callback(const struct option *opt, const char *arg, int unset)
 }
 
 static const struct option show_ref_options[] = {
-	OPT_BOOLEAN(0, "tags", &tags_only, N_("only show tags (can be combined with heads)")),
-	OPT_BOOLEAN(0, "heads", &heads_only, N_("only show heads (can be combined with tags)")),
-	OPT_BOOLEAN(0, "verify", &verify, N_("stricter reference checking, "
+	OPT_BOOL(0, "tags", &tags_only, N_("only show tags (can be combined with heads)")),
+	OPT_BOOL(0, "heads", &heads_only, N_("only show heads (can be combined with tags)")),
+	OPT_BOOL(0, "verify", &verify, N_("stricter reference checking, "
 		    "requires exact ref path")),
 	OPT_HIDDEN_BOOL('h', NULL, &show_head,
 			N_("show the HEAD reference, even if it would be filtered out")),
-	OPT_BOOLEAN(0, "head", &show_head,
+	OPT_BOOL(0, "head", &show_head,
 	  N_("show the HEAD reference, even if it would be filtered out")),
-	OPT_BOOLEAN('d', "dereference", &deref_tags,
+	OPT_BOOL('d', "dereference", &deref_tags,
 		    N_("dereference tags into object IDs")),
 	{ OPTION_CALLBACK, 's', "hash", &abbrev, N_("n"),
 	  N_("only show SHA1 hash using <n> digits"),
diff --git a/builtin/tag.c b/builtin/tag.c
index d8ae5aa..b577af5 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -450,12 +450,12 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_CMDMODE('v', "verify", &cmdmode, N_("verify tags"), 'v'),
 
 		OPT_GROUP(N_("Tag creation options")),
-		OPT_BOOLEAN('a', "annotate", &annotate,
+		OPT_BOOL('a', "annotate", &annotate,
 					N_("annotated tag, needs a message")),
 		OPT_CALLBACK('m', "message", &msg, N_("message"),
 			     N_("tag message"), parse_msg_arg),
 		OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
-		OPT_BOOLEAN('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
+		OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
 		OPT_STRING(0, "cleanup", &cleanup_arg, N_("mode"),
 			N_("how to strip spaces and #comments from message")),
 		OPT_STRING('u', "local-user", &keyid, N_("key id"),
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 51d2684..7484d36 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -16,8 +16,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 	int delete = 0, no_deref = 0, flags = 0;
 	struct option options[] = {
 		OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
-		OPT_BOOLEAN('d', NULL, &delete, N_("delete the reference")),
-		OPT_BOOLEAN( 0 , "no-deref", &no_deref,
+		OPT_BOOL('d', NULL, &delete, N_("delete the reference")),
+		OPT_BOOL( 0 , "no-deref", &no_deref,
 					N_("update <refname> not the one it points to")),
 		OPT_END(),
 	};
-- 
1.8.4.rc0.16.g7fca822.dirty

^ permalink raw reply related	[relevance 3%]

* [PATCH 1/4] Build in git-repack
  @ 2013-08-07 14:00  1%   ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-08-07 14:00 UTC (permalink / raw)
  To: pclouds, iveqy, git

From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>

pack-objects learns a few more options to take over what's been done
by git-repack.sh. cmd_repack() becomes a wrapper around
cmd_pack_objects().
---
 Makefile                       |   2 +-
 builtin.h                      |   1 +
 builtin/pack-objects.c         | 279 ++++++++++++++++++++++++++++++++++++++++-
 bulk-checkin.c                 |   2 +-
 contrib/examples/git-repack.sh | 194 ++++++++++++++++++++++++++++
 git-repack.sh                  | 194 ----------------------------
 git.c                          |   1 +
 pack-write.c                   |  13 +-
 pack.h                         |   4 +-
 9 files changed, 488 insertions(+), 202 deletions(-)
 create mode 100755 contrib/examples/git-repack.sh
 delete mode 100755 git-repack.sh

diff --git a/Makefile b/Makefile
index 3588ca1..8bd122b 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -596,6 +595,7 @@ BUILT_INS += git-get-tar-commit-id$X
 BUILT_INS += git-init$X
 BUILT_INS += git-merge-subtree$X
 BUILT_INS += git-peek-remote$X
+BUILT_INS += git-repack$X
 BUILT_INS += git-repo-config$X
 BUILT_INS += git-show$X
 BUILT_INS += git-stage$X
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f069462..1742ea1 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -18,10 +18,17 @@
 #include "refs.h"
 #include "streaming.h"
 #include "thread-utils.h"
+#include "sigchain.h"
 
 static const char *pack_usage[] = {
 	N_("git pack-objects --stdout [options...] [< ref-list | < object-list]"),
 	N_("git pack-objects [options...] base-name [< ref-list | < object-list]"),
+	N_("git pack-objects --repack [options...]"),
+	NULL
+};
+
+static char const * const repack_usage[] = {
+	N_("git repack [options]"),
 	NULL
 };
 
@@ -103,6 +110,15 @@ static struct object_entry *locate_object_entry(const unsigned char *sha1);
 static uint32_t written, written_delta;
 static uint32_t reused, reused_delta;
 
+#define REPACK_IN_PROGRESS		(1 << 0)
+#define REPACK_UPDATE_INFO		(1 << 1)
+#define REPACK_ALL_INTO_ONE		(1 << 2)
+#define REPACK_REMOVE_REDUNDANT		(1 << 3)
+
+static int repack_flags, nr_written_packs;
+static int repack_usedeltabaseoffset;
+static struct string_list written_packs;
+static struct string_list backup_files;
 
 static void *get_delta(struct object_entry *entry)
 {
@@ -792,9 +808,19 @@ static void write_pack_file(void)
 			snprintf(tmpname, sizeof(tmpname), "%s-", base_name);
 			finish_tmp_packfile(tmpname, pack_tmp_name,
 					    written_list, nr_written,
-					    &pack_idx_opts, sha1);
+					    &pack_idx_opts, sha1,
+					    repack_flags & REPACK_IN_PROGRESS ?
+					    &backup_files : NULL);
 			free(pack_tmp_name);
-			puts(sha1_to_hex(sha1));
+			if (repack_flags & REPACK_IN_PROGRESS) {
+				int len = strlen(tmpname);
+				char *s = xmalloc(len + 2);
+				memcpy(s, tmpname, len - 4);
+				memcpy(s + len - 4, ".pack", 6);
+				string_list_append(&written_packs, s);
+				nr_written_packs++;
+			} else
+				puts(sha1_to_hex(sha1));
 		}
 
 		/* mark written objects as written to previous pack */
@@ -2359,7 +2385,8 @@ static void get_object_list(int ac, const char **av)
 	save_commit_buffer = 0;
 	setup_revisions(ac, av, &revs, NULL);
 
-	while (fgets(line, sizeof(line), stdin) != NULL) {
+	while (!(repack_flags & REPACK_IN_PROGRESS) &&
+	       fgets(line, sizeof(line), stdin) != NULL) {
 		int len = strlen(line);
 		if (len && line[len - 1] == '\n')
 			line[--len] = 0;
@@ -2387,6 +2414,30 @@ static void get_object_list(int ac, const char **av)
 		loosen_unused_packed_objects(&revs);
 }
 
+static void rollback_repack(void)
+{
+	struct strbuf dst = STRBUF_INIT;
+	int i, ret;
+	for (i = 0; i < backup_files.nr; i++) {
+		const char *src = backup_files.items[i].string;
+		strbuf_addstr(&dst, src);
+		strbuf_setlen(&dst, dst.len - 4); /* remove .old */
+		ret = rename(src, dst.buf);
+		if (ret)
+			warning("failed to restore %s: %s", src, strerror(errno));
+		strbuf_setlen(&dst, 0);
+	}
+	strbuf_release(&dst);
+	string_list_clear(&backup_files, 0);
+}
+
+static void rollback_repack_on_signal(int signo)
+{
+	rollback_repack();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
 static int option_parse_index_version(const struct option *opt,
 				      const char *arg, int unset)
 {
@@ -2436,11 +2487,12 @@ static int option_parse_ulong(const struct option *opt,
 
 int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 {
+	struct strbuf repack_base_name = STRBUF_INIT;
 	int use_internal_rev_list = 0;
 	int thin = 0;
 	int all_progress_implied = 0;
 	const char *rp_av[6];
-	int rp_ac = 0;
+	int i, rp_ac = 0;
 	int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
 	struct option pack_objects_options[] = {
 		OPT_SET_INT('q', "quiet", &progress,
@@ -2505,6 +2557,16 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 			    N_("pack compression level")),
 		OPT_SET_INT(0, "keep-true-parents", &grafts_replace_parents,
 			    N_("do not hide commits by grafts"), 0),
+
+		OPT_BIT(0, "repack", &repack_flags,
+			N_("repack mode"), REPACK_IN_PROGRESS),
+		OPT_BIT(0, "repack-all", &repack_flags,
+			N_("repack everything into one pack"), REPACK_ALL_INTO_ONE),
+		OPT_BIT(0, "remove-redundant", &repack_flags,
+			N_("remove redundant objects after repack"), REPACK_REMOVE_REDUNDANT),
+		OPT_BIT(0, "update-info", &repack_flags,
+			N_("run git-update-server-info after repack"), REPACK_UPDATE_INFO),
+
 		OPT_END(),
 	};
 
@@ -2556,6 +2618,36 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 	if (delta_search_threads != 1)
 		warning("no threads support, ignoring --threads");
 #endif
+	if ((repack_flags & REPACK_IN_PROGRESS) == 0 &&
+	    (repack_flags & ~REPACK_IN_PROGRESS))
+		die("--repack must be given for any repack related options");
+	if (repack_flags & REPACK_IN_PROGRESS) {
+		if (pack_to_stdout)
+			die("--stdout cannot be used with --repack");
+		if (argc)
+			die("base name cannot be used with --repack");
+
+		rp_av[rp_ac++] = "--all";
+		rp_av[rp_ac++] = "--reflog";
+		use_internal_rev_list = 1;
+
+		grafts_replace_parents = 0; /* --keep-true-parents */
+		ignore_packed_keep = 1;	    /* --honor-pack-keep */
+		non_empty = 1;		    /* --non-empty */
+
+		if (!(repack_flags & REPACK_ALL_INTO_ONE)) {
+			incremental = 1; /* --incremental */
+			rp_av[rp_ac++] = "--unpacked";
+		}
+
+		strbuf_addf(&repack_base_name,
+			    "%s/pack/pack", get_object_directory());
+		base_name = repack_base_name.buf;
+
+		sigchain_push_common(rollback_repack_on_signal);
+		atexit(rollback_repack);
+	}
+
 	if (!pack_to_stdout && !pack_size_limit)
 		pack_size_limit = pack_size_limit_cfg;
 	if (pack_to_stdout && pack_size_limit)
@@ -2598,5 +2690,184 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		fprintf(stderr, "Total %"PRIu32" (delta %"PRIu32"),"
 			" reused %"PRIu32" (delta %"PRIu32")\n",
 			written, written_delta, reused, reused_delta);
+
+	if (!(repack_flags & REPACK_IN_PROGRESS))
+		return 0;
+
+	if (!nr_written_packs) {
+		printf(_("Nothing new to pack.\n"));
+		return 0;
+	}
+
+	/* At this point all new packs should be in place. We can
+	   safely remove old ones */
+	for (i = 0; i < backup_files.nr; i++) {
+		const char *s = backup_files.items[i].string;
+		int ret = unlink(s);
+		if (ret)
+			warning("failed to remove %s: %s", s, strerror(errno));
+	}
+	string_list_clear(&backup_files, 0);
+
+	if (repack_flags & REPACK_REMOVE_REDUNDANT) {
+		struct packed_git *p;
+		struct string_list to_be_removed = STRING_LIST_INIT_DUP;
+
+		/* free_pack_by_name() may have freed a few packs in
+		   write_pack_file() */
+		reprepare_packed_git();
+		for (p = packed_git; p; p = p->next) {
+			if (!p->pack_local || p->pack_keep)
+				continue;
+
+			for (i = 0; i < written_packs.nr; i++) {
+				char *s = written_packs.items[i].string;
+				if (!strcmp(s, p->pack_name))
+					break;
+			}
+			if (i < written_packs.nr)
+				continue;
+
+			string_list_append(&to_be_removed, p->pack_name);
+		}
+		written_packs.strdup_strings = 1;
+		string_list_clear(&written_packs, 0);
+
+		for (i = 0; i < to_be_removed.nr; i++) {
+			char *path = to_be_removed.items[i].string;
+
+			/* Windows limitation on unlink().
+			   See c74faea19e39ca933492f697596310397175c329 */
+			free_pack_by_name(path);
+
+			if (unlink(path))
+				warning("failed to remove %s: %s", path, strerror(errno));
+			strcpy(path + strlen(path)-5, ".idx");
+			if (unlink(path))
+				warning("failed to remove %s: %s", path, strerror(errno));
+		}
+		string_list_clear(&to_be_removed, 0);
+
+		reprepare_packed_git();
+		prune_packed_objects(progress ? PRUNE_PACKED_VERBOSE : 0);
+	}
+
+	if (repack_flags & REPACK_UPDATE_INFO)
+		update_server_info(0);
+
 	return 0;
 }
+
+static int repack_config(const char *k, const char *v, void *cb)
+{
+	if (!strcasecmp(k, "repack.usedeltabaseoffset")) {
+		repack_usedeltabaseoffset = git_config_bool(k, v);
+		return 0;
+	}
+	return git_default_config(k, v, cb);
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix)
+{
+	int all_in_one = 0;
+	int all_in_one_and_unreachable = 0;
+	int unpack_unreachable = 0;
+	int remove_redundant = 0;
+	int no_reuse_delta = 0;
+	int no_reuse_object = 0;
+	int no_update = 0;
+	int quiet = 0;
+	int local = 0;
+
+	struct option opts[] = {
+		OPT_BOOL('a', NULL, &all_in_one,
+			 "pack everything in a single pack"),
+		OPT_BOOL('A', NULL, &all_in_one_and_unreachable,
+			 "same as -a, and turn unreachable objects loose"),
+		OPT_BOOL('d', NULL, &remove_redundant,
+			 "remove redundant packs, and run git-prune-packed"),
+		OPT_BOOL('f', NULL, &no_reuse_delta,
+			 "pass --no-reuse-delta to git-pack-objects"),
+		OPT_BOOL('F', NULL, &no_reuse_object,
+			 "pass --no-reuse-object to git-pack-objects"),
+		OPT_BOOL('n', NULL, &no_update,
+			 "do not run git-update-server-info"),
+		OPT_BOOL('q', NULL, &quiet, "be quiet"),
+		OPT_BOOL('l', NULL, &local,
+			 "pass --local to git-pack-objects"),
+		{ OPTION_ARGUMENT, 0, "window", NULL, "n",
+		 "size of the window used for delta compression", 0 },
+		{ OPTION_ARGUMENT, 0, "window-memory", NULL, "n",
+		  "same as the above, but limit memory size instead of entries count", 0 },
+		{ OPTION_ARGUMENT, 0, "depth", NULL, "n",
+		  "limits the maximum delta depth", 0 },
+		{ OPTION_ARGUMENT, 0, "max-pack-size", NULL, "n",
+		  "maximum size of each packfile", 0},
+		OPT_END(),
+	};
+
+	const char *av[] = { "pack-objects", "--repack",
+			     NULL, /* --[no-]update-info */
+			     NULL, /* --delta-base-offset */
+			     NULL, /* --repack-all */
+			     NULL, /* --remove-redundant */
+			     NULL, /* --no-reuse-delta */
+			     NULL, /* --no-reuse-object */
+			     NULL, /* --local */
+			     NULL, /* -q */
+			     NULL, /* --unpack-unreachable */
+			     NULL, /* --window */
+			     NULL, /* --window-memory */
+			     NULL, /* --depth */
+			     NULL, /* --max-pack-size */
+			     NULL
+	};
+	int ac = 2;
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, opts, repack_usage, 0);
+
+	if (no_update)
+		av[ac++] = "--no-update-info";
+	else
+		av[ac++] = "--update-info";
+	if (repack_usedeltabaseoffset)
+		av[ac++] = "--delta-base-offset";
+	if (all_in_one_and_unreachable) {
+		av[ac++] = "--repack-all";
+		all_in_one = 1;
+		unpack_unreachable = 1;
+	}
+	if (all_in_one)
+		av[ac++] = "--repack-all";
+	if (remove_redundant)
+		av[ac++] = "--remove-redundant";
+	if (no_reuse_delta)
+		av[ac++] = "--no-reuse-delta";
+	if (no_reuse_object)
+		av[ac++] = "--no-reuse-object";
+	if (local)
+		av[ac++] = "--local";
+	if (quiet)
+		av[ac++] = "-q";
+	if ((ac + argc) * sizeof(*av) > sizeof(av))
+		die("Too many options");
+	memcpy(av + ac, argv, argc * sizeof(*argv));
+	ac += argc;
+
+	if (all_in_one && remove_redundant) {
+		struct packed_git *p;
+
+		prepare_packed_git();
+		for (p = packed_git; p; p = p->next) {
+			if (!p->pack_keep &&
+			    unpack_unreachable && remove_redundant) {
+				av[ac++] = "--unpack-unreachable";
+				break;
+			}
+		}
+	}
+
+	return cmd_pack_objects(ac, av, prefix);
+}
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 6b0b6d4..3ca3c55 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -46,7 +46,7 @@ static void finish_bulk_checkin(struct bulk_checkin_state *state)
 	sprintf(packname, "%s/pack/pack-", get_object_directory());
 	finish_tmp_packfile(packname, state->pack_tmp_name,
 			    state->written, state->nr_written,
-			    &state->pack_idx_opts, sha1);
+			    &state->pack_idx_opts, sha1, NULL);
 	for (i = 0; i < state->nr_written; i++)
 		free(state->written[i]);
 
diff --git a/contrib/examples/git-repack.sh b/contrib/examples/git-repack.sh
new file mode 100755
index 0000000..7579331
--- /dev/null
+++ b/contrib/examples/git-repack.sh
@@ -0,0 +1,194 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+#
+
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git repack [options]
+--
+a               pack everything in a single pack
+A               same as -a, and turn unreachable objects loose
+d               remove redundant packs, and run git-prune-packed
+f               pass --no-reuse-delta to git-pack-objects
+F               pass --no-reuse-object to git-pack-objects
+n               do not run git-update-server-info
+q,quiet         be quiet
+l               pass --local to git-pack-objects
+unpack-unreachable=  with -A, do not loosen objects older than this
+ Packing constraints
+window=         size of the window used for delta compression
+window-memory=  same as the above, but limit memory size instead of entries count
+depth=          limits the maximum delta depth
+max-pack-size=  maximum size of each packfile
+"
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
+no_update_info= all_into_one= remove_redundant= unpack_unreachable=
+local= no_reuse= extra=
+while test $# != 0
+do
+	case "$1" in
+	-n)	no_update_info=t ;;
+	-a)	all_into_one=t ;;
+	-A)	all_into_one=t
+		unpack_unreachable=--unpack-unreachable ;;
+	--unpack-unreachable)
+		unpack_unreachable="--unpack-unreachable=$2"; shift ;;
+	-d)	remove_redundant=t ;;
+	-q)	GIT_QUIET=t ;;
+	-f)	no_reuse=--no-reuse-delta ;;
+	-F)	no_reuse=--no-reuse-object ;;
+	-l)	local=--local ;;
+	--max-pack-size|--window|--window-memory|--depth)
+		extra="$extra $1=$2"; shift ;;
+	--) shift; break;;
+	*)	usage ;;
+	esac
+	shift
+done
+
+case "`git config --bool repack.usedeltabaseoffset || echo true`" in
+true)
+	extra="$extra --delta-base-offset" ;;
+esac
+
+PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
+PACKTMP="$PACKDIR/.tmp-$$-pack"
+rm -f "$PACKTMP"-*
+trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
+
+# There will be more repacking strategies to come...
+case ",$all_into_one," in
+,,)
+	args='--unpacked --incremental'
+	;;
+,t,)
+	args= existing=
+	if [ -d "$PACKDIR" ]; then
+		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
+			| sed -e 's/^\.\///' -e 's/\.pack$//'`
+		do
+			if [ -e "$PACKDIR/$e.keep" ]; then
+				: keep
+			else
+				existing="$existing $e"
+			fi
+		done
+		if test -n "$existing" -a -n "$unpack_unreachable" -a \
+			-n "$remove_redundant"
+		then
+			# This may have arbitrary user arguments, so we
+			# have to protect it against whitespace splitting
+			# when it gets run as "pack-objects $args" later.
+			# Fortunately, we know it's an approxidate, so we
+			# can just use dots instead.
+			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
+		fi
+	fi
+	;;
+esac
+
+mkdir -p "$PACKDIR" || exit
+
+args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
+names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
+	exit 1
+if [ -z "$names" ]; then
+	say Nothing new to pack.
+fi
+
+# Ok we have prepared all new packfiles.
+
+# First see if there are packs of the same name and if so
+# if we can move them out of the way (this can happen if we
+# repacked immediately after packing fully.
+rollback=
+failed=
+for name in $names
+do
+	for sfx in pack idx
+	do
+		file=pack-$name.$sfx
+		test -f "$PACKDIR/$file" || continue
+		rm -f "$PACKDIR/old-$file" &&
+		mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
+			failed=t
+			break
+		}
+		rollback="$rollback $file"
+	done
+	test -z "$failed" || break
+done
+
+# If renaming failed for any of them, roll the ones we have
+# already renamed back to their original names.
+if test -n "$failed"
+then
+	rollback_failure=
+	for file in $rollback
+	do
+		mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
+		rollback_failure="$rollback_failure $file"
+	done
+	if test -n "$rollback_failure"
+	then
+		echo >&2 "WARNING: Some packs in use have been renamed by"
+		echo >&2 "WARNING: prefixing old- to their name, in order to"
+		echo >&2 "WARNING: replace them with the new version of the"
+		echo >&2 "WARNING: file.  But the operation failed, and"
+		echo >&2 "WARNING: attempt to rename them back to their"
+		echo >&2 "WARNING: original names also failed."
+		echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
+		for file in $rollback_failure
+		do
+			echo >&2 "WARNING:   old-$file -> $file"
+		done
+	fi
+	exit 1
+fi
+
+# Now the ones with the same name are out of the way...
+fullbases=
+for name in $names
+do
+	fullbases="$fullbases pack-$name"
+	chmod a-w "$PACKTMP-$name.pack"
+	chmod a-w "$PACKTMP-$name.idx"
+	mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
+	mv -f "$PACKTMP-$name.idx"  "$PACKDIR/pack-$name.idx" ||
+	exit
+done
+
+# Remove the "old-" files
+for name in $names
+do
+	rm -f "$PACKDIR/old-pack-$name.idx"
+	rm -f "$PACKDIR/old-pack-$name.pack"
+done
+
+# End of pack replacement.
+
+if test "$remove_redundant" = t
+then
+	# We know $existing are all redundant.
+	if [ -n "$existing" ]
+	then
+		( cd "$PACKDIR" &&
+		  for e in $existing
+		  do
+			case " $fullbases " in
+			*" $e "*) ;;
+			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
+			esac
+		  done
+		)
+	fi
+	git prune-packed ${GIT_QUIET:+-q}
+fi
+
+case "$no_update_info" in
+t) : ;;
+*) git update-server-info ;;
+esac
diff --git a/git-repack.sh b/git-repack.sh
deleted file mode 100755
index 7579331..0000000
--- a/git-repack.sh
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-
-OPTIONS_KEEPDASHDASH=
-OPTIONS_SPEC="\
-git repack [options]
---
-a               pack everything in a single pack
-A               same as -a, and turn unreachable objects loose
-d               remove redundant packs, and run git-prune-packed
-f               pass --no-reuse-delta to git-pack-objects
-F               pass --no-reuse-object to git-pack-objects
-n               do not run git-update-server-info
-q,quiet         be quiet
-l               pass --local to git-pack-objects
-unpack-unreachable=  with -A, do not loosen objects older than this
- Packing constraints
-window=         size of the window used for delta compression
-window-memory=  same as the above, but limit memory size instead of entries count
-depth=          limits the maximum delta depth
-max-pack-size=  maximum size of each packfile
-"
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-no_update_info= all_into_one= remove_redundant= unpack_unreachable=
-local= no_reuse= extra=
-while test $# != 0
-do
-	case "$1" in
-	-n)	no_update_info=t ;;
-	-a)	all_into_one=t ;;
-	-A)	all_into_one=t
-		unpack_unreachable=--unpack-unreachable ;;
-	--unpack-unreachable)
-		unpack_unreachable="--unpack-unreachable=$2"; shift ;;
-	-d)	remove_redundant=t ;;
-	-q)	GIT_QUIET=t ;;
-	-f)	no_reuse=--no-reuse-delta ;;
-	-F)	no_reuse=--no-reuse-object ;;
-	-l)	local=--local ;;
-	--max-pack-size|--window|--window-memory|--depth)
-		extra="$extra $1=$2"; shift ;;
-	--) shift; break;;
-	*)	usage ;;
-	esac
-	shift
-done
-
-case "`git config --bool repack.usedeltabaseoffset || echo true`" in
-true)
-	extra="$extra --delta-base-offset" ;;
-esac
-
-PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
-PACKTMP="$PACKDIR/.tmp-$$-pack"
-rm -f "$PACKTMP"-*
-trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
-
-# There will be more repacking strategies to come...
-case ",$all_into_one," in
-,,)
-	args='--unpacked --incremental'
-	;;
-,t,)
-	args= existing=
-	if [ -d "$PACKDIR" ]; then
-		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
-			| sed -e 's/^\.\///' -e 's/\.pack$//'`
-		do
-			if [ -e "$PACKDIR/$e.keep" ]; then
-				: keep
-			else
-				existing="$existing $e"
-			fi
-		done
-		if test -n "$existing" -a -n "$unpack_unreachable" -a \
-			-n "$remove_redundant"
-		then
-			# This may have arbitrary user arguments, so we
-			# have to protect it against whitespace splitting
-			# when it gets run as "pack-objects $args" later.
-			# Fortunately, we know it's an approxidate, so we
-			# can just use dots instead.
-			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
-		fi
-	fi
-	;;
-esac
-
-mkdir -p "$PACKDIR" || exit
-
-args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
-names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
-	exit 1
-if [ -z "$names" ]; then
-	say Nothing new to pack.
-fi
-
-# Ok we have prepared all new packfiles.
-
-# First see if there are packs of the same name and if so
-# if we can move them out of the way (this can happen if we
-# repacked immediately after packing fully.
-rollback=
-failed=
-for name in $names
-do
-	for sfx in pack idx
-	do
-		file=pack-$name.$sfx
-		test -f "$PACKDIR/$file" || continue
-		rm -f "$PACKDIR/old-$file" &&
-		mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
-			failed=t
-			break
-		}
-		rollback="$rollback $file"
-	done
-	test -z "$failed" || break
-done
-
-# If renaming failed for any of them, roll the ones we have
-# already renamed back to their original names.
-if test -n "$failed"
-then
-	rollback_failure=
-	for file in $rollback
-	do
-		mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
-		rollback_failure="$rollback_failure $file"
-	done
-	if test -n "$rollback_failure"
-	then
-		echo >&2 "WARNING: Some packs in use have been renamed by"
-		echo >&2 "WARNING: prefixing old- to their name, in order to"
-		echo >&2 "WARNING: replace them with the new version of the"
-		echo >&2 "WARNING: file.  But the operation failed, and"
-		echo >&2 "WARNING: attempt to rename them back to their"
-		echo >&2 "WARNING: original names also failed."
-		echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
-		for file in $rollback_failure
-		do
-			echo >&2 "WARNING:   old-$file -> $file"
-		done
-	fi
-	exit 1
-fi
-
-# Now the ones with the same name are out of the way...
-fullbases=
-for name in $names
-do
-	fullbases="$fullbases pack-$name"
-	chmod a-w "$PACKTMP-$name.pack"
-	chmod a-w "$PACKTMP-$name.idx"
-	mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
-	mv -f "$PACKTMP-$name.idx"  "$PACKDIR/pack-$name.idx" ||
-	exit
-done
-
-# Remove the "old-" files
-for name in $names
-do
-	rm -f "$PACKDIR/old-pack-$name.idx"
-	rm -f "$PACKDIR/old-pack-$name.pack"
-done
-
-# End of pack replacement.
-
-if test "$remove_redundant" = t
-then
-	# We know $existing are all redundant.
-	if [ -n "$existing" ]
-	then
-		( cd "$PACKDIR" &&
-		  for e in $existing
-		  do
-			case " $fullbases " in
-			*" $e "*) ;;
-			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
-			esac
-		  done
-		)
-	fi
-	git prune-packed ${GIT_QUIET:+-q}
-fi
-
-case "$no_update_info" in
-t) : ;;
-*) git update-server-info ;;
-esac
diff --git a/git.c b/git.c
index 2025f77..72d1dc9 100644
--- a/git.c
+++ b/git.c
@@ -397,6 +397,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
 		{ "replace", cmd_replace, RUN_SETUP },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
 		{ "reset", cmd_reset, RUN_SETUP },
diff --git a/pack-write.c b/pack-write.c
index ca9e63b..e6aa7e3 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "pack.h"
 #include "csum-file.h"
+#include "string-list.h"
 
 void reset_pack_idx_option(struct pack_idx_option *opts)
 {
@@ -348,10 +349,12 @@ void finish_tmp_packfile(char *name_buffer,
 			 struct pack_idx_entry **written_list,
 			 uint32_t nr_written,
 			 struct pack_idx_option *pack_idx_opts,
-			 unsigned char sha1[])
+			 unsigned char sha1[],
+			 struct string_list *backup_files)
 {
 	const char *idx_tmp_name;
 	char *end_of_name_prefix = strrchr(name_buffer, 0);
+	struct stat st;
 
 	if (adjust_shared_perm(pack_tmp_name))
 		die_errno("unable to make temporary pack file readable");
@@ -368,6 +371,14 @@ void finish_tmp_packfile(char *name_buffer,
 		die_errno("unable to rename temporary pack file");
 
 	sprintf(end_of_name_prefix, "%s.idx", sha1_to_hex(sha1));
+	if (backup_files && !stat(name_buffer, &st)) {
+		struct strbuf old = STRBUF_INIT;
+		strbuf_addf(&old, "%s.old", name_buffer);
+		if (rename(name_buffer, old.buf))
+			die_errno("unable to rename pack %s", name_buffer);
+		string_list_append(backup_files, strbuf_detach(&old, NULL));
+	}
+	backup_file(name_buffer);
 	if (rename(idx_tmp_name, name_buffer))
 		die_errno("unable to rename temporary index file");
 
diff --git a/pack.h b/pack.h
index aa6ee7d..d3f92ad 100644
--- a/pack.h
+++ b/pack.h
@@ -90,7 +90,9 @@ extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned ch
 #define PH_ERROR_PROTOCOL	(-3)
 extern int read_pack_header(int fd, struct pack_header *);
 
+struct string_list;
+
 extern struct sha1file *create_tmp_packfile(char **pack_tmp_name);
-extern void finish_tmp_packfile(char *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, struct pack_idx_option *pack_idx_opts, unsigned char sha1[]);
+extern void finish_tmp_packfile(char *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, struct pack_idx_option *pack_idx_opts, unsigned char sha1[], struct string_list *backup_files);
 
 #endif
-- 
1.8.4.rc1.25.g2793d0a

^ permalink raw reply related	[relevance 1%]

* [PATCH] diff: remove another ternary expression always evaluating to true
@ 2013-08-08 18:55  6% Stefan Beller
  2013-08-08 21:01  2% ` Johannes Schindelin
  2013-08-08 21:36  2% ` Philip Oakley
  0 siblings, 2 replies; 200+ results
From: Stefan Beller @ 2013-08-08 18:55 UTC (permalink / raw)
  To: Jens.Lehmann, johannes.schindelin, gitster, git; +Cc: Stefan Beller

The condition before the changed line dereferences 'one' to query the mode,
so if the condition evaluates to true, the variable one must not be null.
Therefore we do not need the ternary operator depending on one, giving
either one->path or two->path. This always evaluates to one->path, so
we can remove the ternary operator.

The condition and the usage of the ternary operator have been introduced
by the same commit (752c0c24, 2009-10-19, Add the --submodule option to
the diff option family). As that commit message refers to a GitTogether
I'd assume that patch was crafted in a hurry, so maybe overlooking the
need for a ternary operator there.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 diff.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/diff.c b/diff.c
index 80f8439..f30b7e4 100644
--- a/diff.c
+++ b/diff.c
@@ -2252,8 +2252,7 @@ static void builtin_diff(const char *name_a,
 			(!two->mode || S_ISGITLINK(two->mode))) {
 		const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
 		const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
-		show_submodule_summary(o->file, one ? one->path : two->path,
-				line_prefix,
+		show_submodule_summary(o->file, one->path, line_prefix,
 				one->sha1, two->sha1, two->dirty_submodule,
 				meta, del, add, reset);
 		return;
-- 
1.8.4.rc1.25.gd121ba2

^ permalink raw reply related	[relevance 6%]

* Re: [PATCH] diff: remove another ternary expression always evaluating to true
  2013-08-08 18:55  6% [PATCH] diff: remove another ternary expression always evaluating " Stefan Beller
@ 2013-08-08 21:01  2% ` Johannes Schindelin
  2013-08-08 21:22  6%   ` Stefan Beller
  2013-08-08 21:36  2% ` Philip Oakley
  1 sibling, 1 reply; 200+ results
From: Johannes Schindelin @ 2013-08-08 21:01 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jens.Lehmann, gitster, git

Hi Stefan,

On Thu, 8 Aug 2013, Stefan Beller wrote:

> The condition before the changed line dereferences 'one' to query the mode,
> so if the condition evaluates to true, the variable one must not be null.

To show this better, please use -U10 (or some other appropriate context
option) in the future.

> Therefore we do not need the ternary operator depending on one, giving
> either one->path or two->path. This always evaluates to one->path, so we
> can remove the ternary operator.
> 
> The condition and the usage of the ternary operator have been introduced
> by the same commit (752c0c24, 2009-10-19, Add the --submodule option to
> the diff option family). As that commit message refers to a GitTogether
> I'd assume that patch was crafted in a hurry, so maybe overlooking the
> need for a ternary operator there.

If this is my code, I do not need a GitTogether to excuse my sloppiness.
In this particular case, I imagine the appropriate fix is to test for
one->path instead of removing the conditional, though.

Ciao,
Johannes

^ permalink raw reply	[relevance 2%]

* Re: [PATCH] diff: remove another ternary expression always evaluating to true
  2013-08-08 21:01  2% ` Johannes Schindelin
@ 2013-08-08 21:22  6%   ` Stefan Beller
  2013-08-08 21:36  4%     ` Johannes Schindelin
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2013-08-08 21:22 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Jens.Lehmann, gitster, git

[-- Attachment #1: Type: text/plain, Size: 3721 bytes --]

On 08/08/2013 11:01 PM, Johannes Schindelin wrote:
> Hi Stefan,
> 
> On Thu, 8 Aug 2013, Stefan Beller wrote:
> 
>> The condition before the changed line dereferences 'one' to query the mode,
>> so if the condition evaluates to true, the variable one must not be null.
> 
> To show this better, please use -U10 (or some other appropriate context
> option) in the future.
> 
>> Therefore we do not need the ternary operator depending on one, giving
>> either one->path or two->path. This always evaluates to one->path, so we
>> can remove the ternary operator.
>>
>> The condition and the usage of the ternary operator have been introduced
>> by the same commit (752c0c24, 2009-10-19, Add the --submodule option to
>> the diff option family). As that commit message refers to a GitTogether
>> I'd assume that patch was crafted in a hurry, so maybe overlooking the
>> need for a ternary operator there.
> 
> If this is my code, I do not need a GitTogether to excuse my sloppiness.
> In this particular case, I imagine the appropriate fix is to test for
> one->path instead of removing the conditional, though.
> 
> Ciao,
> Johannes
> 

Ok, here is a resend with -U10
I forgot about the -U10 as gitk shows a different number of lines 
of context around. Is there a way to configure gitk to show less lines
of code or a default -U10 for send-email/format-patch?

So you rather propose to have 
-		show_submodule_summary(o->file, one ? one->path : two->path,
+		show_submodule_summary(o->file, one->path ? one->path : two->path,

instead of the patch below?
(The test suite run without any problem using that patch)

Stefan

--8<--
From 3a580c51f0bf70745f26eb5045d646dfead2afd3 Mon Sep 17 00:00:00 2001
From: Stefan Beller <stefanbeller@googlemail.com>
Date: Thu, 8 Aug 2013 20:54:24 +0200
Subject: [PATCH] diff: remove another ternary expression always evaluating to
 true

The condition before the changed line dereferences 'one' to query the mode,
so if the condition evaluates to true, the variable one must not be null.
Therefore we do not need the ternary operator depending on one, giving
either one->path or two->path. This always evaluates to one->path, so
we can remove the ternary operator.

The condition and the usage of the ternary operator have been introduced
by the same commit (752c0c24, 2009-10-19, Add the --submodule option to
the diff option family). As that commit message refers to a GitTogether
I'd assume that patch was crafted in a hurry, so maybe overlooking the
need for a ternary operator there.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 diff.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/diff.c b/diff.c
index 80f8439..f30b7e4 100644
--- a/diff.c
+++ b/diff.c
@@ -2245,22 +2245,21 @@ static void builtin_diff(const char *name_a,
 	struct userdiff_driver *textconv_one = NULL;
 	struct userdiff_driver *textconv_two = NULL;
 	struct strbuf header = STRBUF_INIT;
 	const char *line_prefix = diff_line_prefix(o);
 
 	if (DIFF_OPT_TST(o, SUBMODULE_LOG) &&
 			(!one->mode || S_ISGITLINK(one->mode)) &&
 			(!two->mode || S_ISGITLINK(two->mode))) {
 		const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
 		const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
-		show_submodule_summary(o->file, one ? one->path : two->path,
-				line_prefix,
+		show_submodule_summary(o->file, one->path, line_prefix,
 				one->sha1, two->sha1, two->dirty_submodule,
 				meta, del, add, reset);
 		return;
 	}
 
 	if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
 		textconv_one = get_textconv(one);
 		textconv_two = get_textconv(two);
 	}
 
-- 
1.8.4.rc1.25.gd121ba2



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply related	[relevance 6%]

* Re: [PATCH] diff: remove another ternary expression always evaluating to true
  2013-08-08 21:22  6%   ` Stefan Beller
@ 2013-08-08 21:36  4%     ` Johannes Schindelin
  2013-08-08 22:03  0%       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Johannes Schindelin @ 2013-08-08 21:36 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jens.Lehmann, gitster, git

Hi Stefan,

On Thu, 8 Aug 2013, Stefan Beller wrote:

> So you rather propose to have 
> -		show_submodule_summary(o->file, one ? one->path : two->path,
> +		show_submodule_summary(o->file, one->path ? one->path : two->path,

I do. The reason is that one->path could be NULL (but not both one->path
and two->path) and the summary would not be as helpful as possible if it
wrote "(null)" instead of the path of the submodule.

Ciao,
Johannes

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] diff: remove another ternary expression always evaluating to true
  2013-08-08 18:55  6% [PATCH] diff: remove another ternary expression always evaluating " Stefan Beller
  2013-08-08 21:01  2% ` Johannes Schindelin
@ 2013-08-08 21:36  2% ` Philip Oakley
  1 sibling, 0 replies; 200+ results
From: Philip Oakley @ 2013-08-08 21:36 UTC (permalink / raw)
  To: Stefan Beller, git; +Cc: Jens.Lehmann, johannes.schindelin, gitster

From: "Stefan Beller" <stefanbeller@googlemail.com>
Sent: Thursday, August 08, 2013 7:55 PM
Subject: [PATCH] diff: remove another ternary expression always 
evaluating to true

Have these issues (and the earlier expression simplifications patches 
$gmane/231916, $gmane/231912 ) been discovered with the "STACK" tool I'd 
noted in $gmane/230542 which you were also interested in (I've not had 
chance to run the tool).

If so, it's probably worth referencing the tool and the paper which 
explains the broader issues.

Philip


> The condition before the changed line dereferences 'one' to query the 
> mode,
> so if the condition evaluates to true, the variable one must not be 
> null.
> Therefore we do not need the ternary operator depending on one, giving
> either one->path or two->path. This always evaluates to one->path, so
> we can remove the ternary operator.
>
> The condition and the usage of the ternary operator have been 
> introduced
> by the same commit (752c0c24, 2009-10-19, Add the --submodule option 
> to
> the diff option family). As that commit message refers to a 
> GitTogether
> I'd assume that patch was crafted in a hurry, so maybe overlooking the
> need for a ternary operator there.
>
> Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
> ---
> diff.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/diff.c b/diff.c
> index 80f8439..f30b7e4 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -2252,8 +2252,7 @@ static void builtin_diff(const char *name_a,
>  (!two->mode || S_ISGITLINK(two->mode))) {
>  const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
>  const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
> - show_submodule_summary(o->file, one ? one->path : two->path,
> - line_prefix,
> + show_submodule_summary(o->file, one->path, line_prefix,
>  one->sha1, two->sha1, two->dirty_submodule,
>  meta, del, add, reset);
>  return;
> -- 
> 1.8.4.rc1.25.gd121ba2
>
> --

^ permalink raw reply	[relevance 2%]

* Re: [PATCH] diff: remove another ternary expression always evaluating to true
  2013-08-08 21:36  4%     ` Johannes Schindelin
@ 2013-08-08 22:03  0%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2013-08-08 22:03 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Stefan Beller, Jens.Lehmann, git

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

> Hi Stefan,
>
> On Thu, 8 Aug 2013, Stefan Beller wrote:
>
>> So you rather propose to have 
>> -		show_submodule_summary(o->file, one ? one->path : two->path,
>> +		show_submodule_summary(o->file, one->path ? one->path : two->path,
>
> I do. The reason is that one->path could be NULL (but not both one->path
> and two->path) and the summary would not be as helpful as possible if it
> wrote "(null)" instead of the path of the submodule.

Good.

Also some C libraries would choke when asked to %s format a NULL,
instead of giving "(null)" to avoid segfaulting (which I think is a
quirk in glibc).

^ permalink raw reply	[relevance 0%]

* [ANNOUNCE] Git v1.8.4-rc2
@ 2013-08-08 23:02  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2013-08-08 23:02 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate Git v1.8.4-rc2 is now available for testing
at the usual places.

There are only a handful of small documentation and test updates
since -rc1, except one notable change for Cygwin users.  We no
longer use a custom "fast but cheating" lstat(2) emulation and
instead use the platform one.

The release tarballs are found at:

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

and their SHA-1 checksums are:

1477b3def09d3b10a94441881b1aa19eb7f6586f  git-1.8.4.rc2.tar.gz
554ae8d0125c93bfdfa508bbe35a2375c82c545a  git-htmldocs-1.8.4.rc2.tar.gz
92a36c67f0def3544bcbd09bced2779142433ba5  git-manpages-1.8.4.rc2.tar.gz

The following public repositories all have a copy of the v1.8.4-rc2
tag and the master branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v1.8.4 Release Notes (draft)
========================

Backward compatibility notes (for Git 2.0)
------------------------------------------

When "git push [$there]" does not say what to push, we have used the
traditional "matching" semantics so far (all your branches were sent
to the remote as long as there already are branches of the same name
over there).  In Git 2.0, the default will change to the "simple"
semantics that pushes:

 - only the current branch to the branch with the same name, and only
   when the current branch is set to integrate with that remote
   branch, if you are pushing to the same remote as you fetch from; or

 - only the current branch to the branch with the same name, if you
   are pushing to a remote that is not where you usually fetch from.

Use the user preference configuration variable "push.default" to
change this.  If you are an old-timer who is used to the "matching"
semantics, you can set the variable to "matching" to keep the
traditional behaviour.  If you want to live in the future early, you
can set it to "simple" today without waiting for Git 2.0.

When "git add -u" (and "git add -A") is run inside a subdirectory and
does not specify which paths to add on the command line, it
will operate on the entire tree in Git 2.0 for consistency
with "git commit -a" and other commands.  There will be no
mechanism to make plain "git add -u" behave like "git add -u .".
Current users of "git add -u" (without a pathspec) should start
training their fingers to explicitly say "git add -u ."
before Git 2.0 comes.  A warning is issued when these commands are
run without a pathspec and when you have local changes outside the
current directory, because the behaviour in Git 2.0 will be different
from today's version in such a situation.

In Git 2.0, "git add <path>" will behave as "git add -A <path>", so
that "git add dir/" will notice paths you removed from the directory
and record the removal.  Versions before Git 2.0, including this
release, will keep ignoring removals, but the users who rely on this
behaviour are encouraged to start using "git add --ignore-removal <path>"
now before 2.0 is released.


Updates since v1.8.3
--------------------

Foreign interfaces, subsystems and ports.

 * Cygwin port has been updated for more recent Cygwin 1.7.

 * "git rebase -i" now honors --strategy and -X options.

 * Git-gui has been updated to its 0.18.0 version.

 * MediaWiki remote helper (in contrib/) has been updated to use the
   credential helper interface from Git.pm.

 * Update build for Cygwin 1.[57].  Torsten Bögershausen reports that
   this is fine with Cygwin 1.7 ($gmane/225824) so let's try moving it
   ahead.

 * The credential helper to talk to keychain on OS X (in contrib/) has
   been updated to kick in not just when talking http/https but also
   imap(s) and smtp.

 * Remote transport helper has been updated to report errors and
   maintain ref hierarchy used to keep track of its own state better.

 * With "export" remote-helper protocol, (1) a push that tries to
   update a remote ref whose name is different from the pushing side
   does not work yet, and (2) the helper may not know how to do
   --dry-run; these problematic cases are disabled for now.

 * git-remote-hg/bzr (in contrib/) updates.

 * git-remote-mw (in contrib/) hints users to check the certificate,
   when https:// connection failed.

 * git-remote-mw (in contrib/) adds a command to allow previewing the
   contents locally before pushing it out, when working with a
   MediaWiki remote.


UI, Workflows & Features

 * Sample "post-receive-email" hook script got an enhanced replacement
   "multimail" (in contrib/).

 * Also in contrib/ is a new "contacts" script that runs "git blame"
   to find out the people who may be interested in a set of changes.

 * "git clean" command learned an interactive mode.

 * The "--head" option to "git show-ref" was only to add "HEAD" to the
   list of candidate refs to be filtered by the usual rules
   (e.g. "--heads" that only show refs under refs/heads).  The meaning
   of the option has been changed to always show "HEAD" regardless of
   what filtering will be applied to any other ref.

   This is a backward incompatible change and might cause breakages to
   people's existing scripts.

 * "git show -s" was less discoverable than it should have been.  It
   now has a natural synonym "git show --no-patch".

 * "git check-mailmap" is a new command that lets you map usernames
   and e-mail addresses through the mailmap mechanism, just like many
   built-in commands do.

 * "git name-rev" learned to name an annotated tag object back to its
   tagname; "git name-rev $(git rev-parse v1.0.0)" gives "tags/v1.0.0",
   for example.

 * "git cat-file --batch-check=<format>" is added, primarily to allow
   on-disk footprint of objects in packfiles (often they are a lot
   smaller than their true size, when expressed as deltas) to be
   reported.

 * "git rebase [-i]" used to leave just "rebase" as its reflog messages
   for some operations. They have been reworded to be more informative.

 * In addition to the choice from "rebase, merge, or checkout-detach",
   "submodule update" can allow a custom command to be used in to
   update the working tree of submodules via the "submodule.*.update"
   configuration variable.

 * "git submodule update" can optionally clone the submodule
   repositories shallowly.

 * "git format-patch" learned "--from[=whom]" option, which sets the
   "From: " header to the specified person (or the person who runs the
   command, if "=whom" part is missing) and move the original author
   information to an in-body From: header as necessary.

 * The configuration variable "merge.ff" was cleary a tri-state to
   choose one from "favor fast-forward when possible", "always create
   a merge even when the history could fast-forward" and "do not
   create any merge, only update when the history fast-forwards", but
   the command line parser did not implement the usual convention of
   "last one wins, and command line overrides the configuration"
   correctly.

 * "gitweb" learned to optionally place extra links that point at the
   levels higher than the Gitweb pages themselves in the breadcrumbs,
   so that it can be used as part of a larger installation.

 * "git log --format=" now honors i18n.logoutputencoding configuration
   variable.

 * The "push.default=simple" mode of "git push" has been updated to
   behave like "current" without requiring a remote tracking
   information, when you push to a remote that is different from where
   you fetch from (i.e. a triangular workflow).

 * Having multiple "fixup!" on a line in the rebase instruction sheet
   did not work very well with "git rebase -i --autosquash".

 * "git log" learned the "--author-date-order" option, with which the
   output is topologically sorted and commits in parallel histories
   are shown intermixed together based on the author timestamp.

 * Various subcommands of "git submodule" refused to run from anywhere
   other than the top of the working tree of the superproject, but
   they have been taught to let you run from a subdirectory.

 * "git diff" learned a mode that ignores hunks whose change consists
   only of additions and removals of blank lines, which is the same as
   "diff -B" (ignore blank lines) of GNU diff.

 * "git rm" gives a single message followed by list of paths to report
   multiple paths that cannot be removed.

 * "git rebase" can be told with ":/look for this string" syntax commits
   to replay the changes onto and where the work to be replayed begins.

 * Many tutorials teach users to set "color.ui" to "auto" as the first
   thing after you set "user.name/email" to introduce yourselves to
   Git.  Now the variable defaults to "auto".

 * On Cygwin, "cygstart" is now recognised as a possible way to start
   a web browser (used in "help -w" and "instaweb" among others).

 * "git status" learned status.branch and status.short configuration
   variables to use --branch and --short options by default (override
   with --no-branch and --no-short options from the command line).

 * "git cmd <name>", when <name> happens to be a 40-hex string,
   directly uses the 40-hex string as an object name, even if a ref
   "refs/<some hierarchy>/<name>" exists.  This disambiguation order
   is unlikely to change, but we should warn about the ambiguity just
   like we warn when more than one refs/ hierarchies share the same
   name.

 * "git rebase" learned "--[no-]autostash" option to save local
   changes instead of refusing to run (to which people's normal
   response was to stash them and re-run).  This introduced a corner
   case breakage to "git am --abort" but it has been fixed.

 * Instead of typing four capital letters "HEAD", you can say "@" now,
   e.g. "git log @".

 * "check-ignore" (new feature since 1.8.2) has been updated to work
   more like "check-attr" over bidi-pipes.

 * "git describe" learned "--first-parent" option to limit its closest
   tagged commit search to the first-parent chain.

 * "git merge foo" that might have meant "git merge origin/foo" is
   diagnosed with a more informative error message.

 * "git log -L<line>,<range>:<filename>" has been added.  This may
   still have leaks and rough edges, though.

 * We used the approxidate() parser for "--expire=<timestamp>" options
   of various commands, but it is better to treat --expire=all and
   --expire=now a bit more specially than using the current timestamp.
   "git gc" and "git reflog" have been updated with a new parsing
   function for expiry dates.

 * Updates to completion (both bash and zsh) helpers.

 * The behaviour of the "--chain-reply-to" option of "git send-email"
   have changed at 1.7.0, and we added a warning/advice message to
   help users adjust to the new behaviour back then, but we kept it
   around for too long.  The message has finally been removed.

 * "git fetch origin master" unlike "git fetch origin" or "git fetch"
   did not update "refs/remotes/origin/master"; this was an early
   design decision to keep the update of remote tracking branches
   predictable, but in practice it turns out that people find it more
   convenient to opportunistically update them whenever we have a
   chance, and we have been updating them when we run "git push" which
   already breaks the original "predictability" anyway.

 * The configuration variable core.checkstat was advertised in the
   documentation but the code expected core.statinfo instead.
   For now, we accept both core.checkstat and core.statinfo, but the
   latter will be removed in the longer term.


Performance, Internal Implementation, etc.

 * On Cygwin, we used to use our own lstat(2) emulation that is
   allegedly faster than the platform one in codepaths where some of
   the information it returns did not matter, but it started to bite
   us in a few codepaths where the trick it uses to cheat does show
   breakages. This emulation has been removed and we use the native
   lstat(2) emulation supplied by Cygwin now.

 * The function attributes extensions are used to catch mistakes in
   use of our own variadic functions that use NULL sentinel at the end
   (i.e. like execl(3)) and format strings (i.e. like printf(3)).

 * The code to allow configuration data to be read from in-tree blob
   objects is in.  This may help working in a bare repository and
   submodule updates.

 * Fetching between repositories with many refs employed O(n^2)
   algorithm to match up the common objects, which has been corrected.

 * The original way to specify remote repository using .git/branches/
   used to have a nifty feature.  The code to support the feature was
   still in a function but the caller was changed not to call it 5
   years ago, breaking that feature and leaving the supporting code
   unreachable.  The dead code has been removed.

 * "git pack-refs" that races with new ref creation or deletion have
   been susceptible to lossage of refs under right conditions, which
   has been tightened up.

 * We read loose and packed rerferences in two steps, but after
   deciding to read a loose ref but before actually opening it to read
   it, another process racing with us can unlink it, which would cause
   us to barf.  The codepath has been updated to retry when such a
   race is detected, instead of outright failing.

 * Uses of the platform fnmatch(3) function (many places in the code,
   matching pathspec, .gitignore and .gitattributes to name a few)
   have been replaced with wildmatch, allowing "foo/**/bar" that would
   match foo/bar, foo/a/bar, foo/a/b/bar, etc.

 * Memory ownership and lifetime rules for what for-each-ref feeds to
   its callbacks have been clarified (in short, "you do not own it, so
   make a copy if you want to keep it").

 * The revision traversal logic to improve culling of irrelevant
   parents while traversing a mergy history has been updated.

 * Some leaks in unpack-trees (used in merge, cherry-pick and other
   codepaths) have been plugged.

 * The codepath to read from marks files in fast-import/export did not
   have to accept anything but 40-hex representation of the object
   name.  Further, fast-export did not need full in-core object
   representation to have parsed wen reading from them.  These
   codepaths have been optimized by taking advantage of these access
   patterns.

 * Object lookup logic, when the object hashtable starts to become
   crowded, has been optimized.

 * When TEST_OUTPUT_DIRECTORY setting is used, it was handled somewhat
   inconsistently between the test framework and t/Makefile, and logic
   to summarize the results looked at a wrong place.

 * "git clone" uses a lighter-weight implementation when making sure
   that the history behind refs are complete.

 * Many warnings from sparse source checker in compat/ area has been
   squelched.

 * The code to reading and updating packed-refs file has been updated,
   correcting corner case bugs.


Also contains various documentation updates and code clean-ups.


Fixes since v1.8.3
------------------

Unless otherwise noted, all the fixes since v1.8.3 in the maintenance
track are contained in this release (see release notes to them for
details).

 * Newer Net::SMTP::SSL module does not want the user programs to use
   the default behaviour to let server certificate go without
   verification, so by default enable the verification with a
   mechanism to turn it off if needed.
   (merge 35035bb rr/send-email-ssl-verify later to maint).

 * When "git" is spawned in such a way that any of the low 3 file
   descriptors is closed, our first open() may yield file descriptor 2,
   and writing error message to it would screw things up in a big way.
   (merge a11c396 tr/protect-low-3-fds later to maint).

 * The mailmap mechanism unnecessarily downcased the e-mail addresses
   in the output, and also ignored the human name when it is a single
   character name.
   (merge bd23794 jc/mailmap-case-insensitivity later to maint).

 * In two places we did not check return value (expected to be a file
   descriptor) correctly.
   (merge a77f106 tr/fd-gotcha-fixes later to maint).

 * Logic to auto-detect character encodings in the commit log message
   did not reject overlong and invalid UTF-8 characters.
   (merge 81050ac bc/commit-invalid-utf8 later to maint).

 * Pass port number as a separate argument when "send-email" initializes
   Net::SMTP, instead of as a part of the hostname, i.e. host:port.
   This allows GSSAPI codepath to match with the hostname given.
   (merge 1a741bf bc/send-email-use-port-as-separate-param later to maint).

 * "git diff" refused to even show difference when core.safecrlf is
   set to true (i.e. error out) and there are offending lines in the
   working tree files.
   (merge 5430bb2 jc/maint-diff-core-safecrlf later to maint).

 * A test that should have failed but didn't revealed a bug that needs
   to be corrected.
   (merge 94d75d1 jc/t1512-fix later to maint).

 * An overlong path to a .git directory may have overflown the
   temporary path buffer used to create a name for lockfiles.
   (merge 2fbd4f9 mh/maint-lockfile-overflow later to maint).

 * Invocations of "git checkout" used internally by "git rebase" were
   counted as "checkout", and affected later "git checkout -" to the
   the user to an unexpected place.
   (merge 3bed291 rr/rebase-checkout-reflog later to maint).

 * "git stash save", when your local change turns a tracked file into
   a directory, has to remove files in that directory in order to
   revert your working tree to a pristine state.  This will lose
   untracked files in such a directory, and the command now requires
   you to "--force" it.

 * The configuration variable column.ui was poorly documented.
   (merge 5e62cc1 rr/column-doc later to maint).

 * "git name-rev --refs=tags/v*" were forbidden, which was a bit
   inconvenient (you had to give a pattern to match refs fully, like
   --refs=refs/tags/v*).
   (merge 98c5c4a nk/name-rev-abbreviated-refs later to maint).

 * "git apply" parsed patches that add new files, generated by
   programs other than Git, incorrectly.  This is an old breakage in
   v1.7.11 and will need to be merged down to the maintanance tracks.

 * Older cURL wanted piece of memory we call it with to be stable, but
   we updated the auth material after handing it to a call.

 * "git pull" into nothing trashed "local changes" that were in the
   index, and this avoids it.

 * Many "git submodule" operations do not work on a submodule at a
   path whose name is not in ASCII.

 * "cherry-pick" had a small leak in an error codepath.

 * Logic used by git-send-email to suppress cc mishandled names like
   "A U. Thor" <author@example.xz>, where the human readable part
   needs to be quoted (the user input may not have the double quotes
   around the name, and comparison was done between quoted and
   unquoted strings).  It also mishandled names that need RFC2047
   quoting.

 * Call to discard_cache/discard_index (used when we use different
   contents of the index in-core, in many operations like commit,
   apply, and merge) used to leak memory that held the array of index
   entries, which has been plugged.
   (merge a0fc4db rs/discard-index-discard-array later to maint).

 * "gitweb" forgot to clear a global variable $search_regexp upon each
   request, mistakenly carrying over the previous search to a new one
   when used as a persistent CGI.

 * The wildmatch engine did not honor WM_CASEFOLD option correctly.

 * "git log -c --follow $path" segfaulted upon hitting the commit that
   renamed the $path being followed.

 * When a reflog notation is used for implicit "current branch", we
   did not say which branch and worse said "branch ''".

 * "difftool --dir-diff" did not copy back changes made by the
   end-user in the diff tool backend to the working tree in some
   cases.

 * "git push $there HEAD:branch" did not resolve HEAD early enough, so
   it was easy to flip it around while push is still going on and push
   out a branch that the user did not originally intended when the
   command was started.

 * The bash prompt code (in contrib/) displayed the name of the branch
   being rebased when "rebase -i/-m/-p" modes are in use, but not the
   plain vanilla "rebase".

 * Handling of negative exclude pattern for directories "!dir" was
   broken in the update to v1.8.3.

 * zsh prompt script that borrowed from bash prompt script did not
   work due to slight differences in array variable notation between
   these two shells.

 * An entry for "file://" scheme in the enumeration of URL types Git
   can take in the HTML documentation was made into a clickable link
   by mistake.

 * "git push --[no-]verify" was not documented.

 * Stop installing the git-remote-testpy script that is only used for
   testing.

 * "git commit --allow-empty-message -m ''" should not start an
   editor.

 * "git merge @{-1}~22" was rewritten to "git merge frotz@{1}~22"
   incorrectly when your previous branch was "frotz" (it should be
   rewritten to "git merge frotz~22" instead).

 * "git diff -c -p" was not showing a deleted line from a hunk when
   another hunk immediately begins where the earlier one ends.

 * "git log --ancestry-path A...B" did not work as expected, as it did
   not pay attention to the fact that the merge base between A and B
   was the bottom of the range being specified.

 * Mac OS X does not like to write(2) more than INT_MAX number of
   bytes; work it around by chopping write(2) into smaller pieces.

 * Newer MacOS X encourages the programs to compile and link with
   their CommonCrypto, not with OpenSSL.

 * "git clone foo/bar:baz" cannot be a request to clone from a remote
   over git-over-ssh specified in the scp style.  This case is now
   detected and clones from a local repository at "foo/bar:baz".

 * When $HOME is misconfigured to point at an unreadable directory, we
   used to complain and die. Loosen the check.

 * "git subtree" (in contrib/) had one codepath with loose error
   checks to lose data at the remote side.

 * "git fetch" into a shallow repository from a repository that does
   not know about the shallow boundary commits (e.g. a different fork
   from the repository the current shallow repository was cloned from)
   did not work correctly.

 * "git checkout foo" DWIMs the intended "upstream" and turns it into
   "git checkout -t -b foo remotes/origin/foo". This codepath has been
   updated to correctly take existing remote definitions into account.

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

Changes since v1.8.4-rc1 are as follows:

Brian M. Carlson (1):
      Add missing test file for UTF-16.

Felix Gruber (1):
      fix typo in documentation of git-svn

Jiang Xin (2):
      l10n: git.pot: v1.8.4 round 1 (99 new, 46 removed)
      l10n: zh_CN.po: translate 99 messages (2133t0f0u)

Jonathan Nieder (1):
      log doc: the argument to --encoding is not optional

Junio C Hamano (4):
      Revert "cat-file: split --batch input lines on whitespace"
      t3900: test rejecting log message with NULs correctly
      commit: typofix for xxFFF[EF] check
      Git 1.8.4-rc2

Ramsay Allan Jones (1):
      cygwin: Remove the Win32 l/stat() implementation

René Scharfe (1):
      t8001, t8002: fix "blame -L :literal" test on NetBSD

Stefan Beller (1):
      .mailmap: Multiple addresses of Michael S. Tsirkin

Torstein Hegge (1):
      Documentation/rev-list-options: add missing word in --*-parents

Tran Ngoc Quan (1):
      l10n: vi.po (2133t)

^ permalink raw reply	[relevance 2%]

* Re: [PATCH] diff: remove ternary operator evaluating always to true
  @ 2013-08-12  5:46  2%   ` Junio C Hamano
  2013-08-12  8:32  5%     ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2013-08-12  5:46 UTC (permalink / raw)
  To: Jeff King; +Cc: Stefan Beller, git

Jeff King <peff@peff.net> writes:

> On Thu, Aug 08, 2013 at 08:31:44PM +0200, Stefan Beller wrote:
>
>> The next occurrences are at:
>> 	/* Never use a non-valid filename anywhere if at all possible */
>> 	name_a = DIFF_FILE_VALID(one) ? name_a : name_b;
>> 	name_b = DIFF_FILE_VALID(two) ? name_b : name_a;
>> 
>> 	a_one = quote_two(a_prefix, name_a + (*name_a == '/'));
>> 	b_two = quote_two(b_prefix, name_b + (*name_b == '/'));
>> 
>> In the last line of this block 'name_b' is dereferenced and compared
>> to '/'. This would crash if name_b was NULL. Hence in the following code
>> we can assume name_b being non-null.
>
> I think your change is correct, but I find the reasoning above a little
> suspect. It assumes that the second chunk of code (accessing name_a and
> name_b) is correct, and pins the correctness of the code you are
> changing to it. If the second chunk is buggy, then you are actually
> making the code worse.

True.  I think the original code structure design is name_a should
always exist but name_b may not (the caller of run_diff_cmd() that
eventually calls this call these "name" and "other", and the intent
is renaming filepair is what needs "other").

> I wonder if the implicit expectation of the function to take at least
> one non-NULL name would be more obvious if the first few lines were
> written as:
>
>   if (DIFF_FILE_VALID(one)) {
>           if (!DIFF_FILE_VALID(two))
>                   name_b = name_a;
>   } else if (DIFF_FILE_VALID(two))
>           name_a = name_b;
>   else
>           die("BUG: two invalid files to diff");
>
> That covers all of the cases explicitly, though it is IMHO uglier to
> read (and there is still an implicit assumption that the name is
> non-NULL if DIFF_FILE_VALID() is true).

I think that is an overall improvement, especially if we also update
the checks of {one,two}->mode made for the block that deals with
submodules to use DIFF_FILE_VALID().

Thanks.

^ permalink raw reply	[relevance 2%]

* Re: [PATCH] diff: remove ternary operator evaluating always to true
  2013-08-12  5:46  2%   ` Junio C Hamano
@ 2013-08-12  8:32  5%     ` Stefan Beller
  2013-08-12 17:15  2%       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2013-08-12  8:32 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, git

[-- Attachment #1: Type: text/plain, Size: 4270 bytes --]

On 08/12/2013 07:46 AM, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
> 
>> On Thu, Aug 08, 2013 at 08:31:44PM +0200, Stefan Beller wrote:
>>
>>> The next occurrences are at:
>>> 	/* Never use a non-valid filename anywhere if at all possible */
>>> 	name_a = DIFF_FILE_VALID(one) ? name_a : name_b;
>>> 	name_b = DIFF_FILE_VALID(two) ? name_b : name_a;
>>>
>>> 	a_one = quote_two(a_prefix, name_a + (*name_a == '/'));
>>> 	b_two = quote_two(b_prefix, name_b + (*name_b == '/'));
>>>
>>> In the last line of this block 'name_b' is dereferenced and compared
>>> to '/'. This would crash if name_b was NULL. Hence in the following code
>>> we can assume name_b being non-null.
>>
>> I think your change is correct, but I find the reasoning above a little
>> suspect. It assumes that the second chunk of code (accessing name_a and
>> name_b) is correct, and pins the correctness of the code you are
>> changing to it. If the second chunk is buggy, then you are actually
>> making the code worse.
> 
> True.  I think the original code structure design is name_a should
> always exist but name_b may not (the caller of run_diff_cmd() that
> eventually calls this call these "name" and "other", and the intent
> is renaming filepair is what needs "other").
> 
>> I wonder if the implicit expectation of the function to take at least
>> one non-NULL name would be more obvious if the first few lines were
>> written as:
>>
>>   if (DIFF_FILE_VALID(one)) {
>>           if (!DIFF_FILE_VALID(two))
>>                   name_b = name_a;
>>   } else if (DIFF_FILE_VALID(two))
>>           name_a = name_b;
>>   else
>>           die("BUG: two invalid files to diff");
>>
>> That covers all of the cases explicitly, though it is IMHO uglier to
>> read (and there is still an implicit assumption that the name is
>> non-NULL if DIFF_FILE_VALID() is true).
> 
> I think that is an overall improvement, especially if we also update
> the checks of {one,two}->mode made for the block that deals with
> submodules to use DIFF_FILE_VALID().
> 
> Thanks.
> 

So, do I understand your reasoning, when proposing this patch?
(This may break whitespaces as it's copied into my MUA, will resend with
git send-mail if you think this is the right thing.)

This patch just covers your discussion and not the previous patches.

Stefan

--8<--
From 701bab4f15598ba230552af7f1d5719187f1b2e8 Mon Sep 17 00:00:00 2001
From: Stefan Beller <stefanbeller@googlemail.com>
Date: Mon, 12 Aug 2013 10:29:07 +0200
Subject: [PATCH] diff: Additional error checking for input parameters

This makes the diff function error out instead of segfaulting if the
parameters are bad.

Helped-by: Jeff King <peff@peff.net>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 diff.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/diff.c b/diff.c
index e53ddad..de21971 100644
--- a/diff.c
+++ b/diff.c
@@ -2254,8 +2254,11 @@ static void builtin_diff(const char *name_a,
 			(!two->mode || S_ISGITLINK(two->mode))) {
 		const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
 		const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
-		show_submodule_summary(o->file, one ? one->path : two->path,
-				line_prefix,
+		struct diff_filespec *spec = one && DIFF_FILE_VALID(one) ? one : two;
+		if (!spec && !DIFF_FILE_VALID(spec))
+			die("BUG: two invalid diff_filespec structs in diff");
+
+		show_submodule_summary(o->file, spec->path, line_prefix,
 				one->sha1, two->sha1, two->dirty_submodule,
 				meta, del, add, reset);
 		return;
@@ -2276,8 +2279,13 @@ static void builtin_diff(const char *name_a,
 	}
 
 	/* Never use a non-valid filename anywhere if at all possible */
-	name_a = DIFF_FILE_VALID(one) ? name_a : name_b;
-	name_b = DIFF_FILE_VALID(two) ? name_b : name_a;
+	if (DIFF_FILE_VALID(one)) {
+		if (!DIFF_FILE_VALID(two))
+			name_b = name_a;
+	} else if (DIFF_FILE_VALID(two))
+		name_a = name_b;
+	else
+		die("BUG: two invalid files to diff");
 
 	a_one = quote_two(a_prefix, name_a + (*name_a == '/'));
 	b_two = quote_two(b_prefix, name_b + (*name_b == '/'));
-- 
1.8.4.rc2



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply related	[relevance 5%]

* Re: [PATCH] diff: remove ternary operator evaluating always to true
  2013-08-12  8:32  5%     ` Stefan Beller
@ 2013-08-12 17:15  2%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2013-08-12 17:15 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jeff King, git

Stefan Beller <stefanbeller@googlemail.com> writes:

> On 08/12/2013 07:46 AM, Junio C Hamano wrote:
>> I think that is an overall improvement, especially if we also update
>> the checks of {one,two}->mode made for the block that deals with
>> submodules to use DIFF_FILE_VALID().
>> 
>> Thanks.
>> 
>
> So, do I understand your reasoning, when proposing this patch?

I meant the condition in the "if" statement, not the parameters to
show_submodule_summary().  There are checks on ->mode fields that
bypass the DIFF_FILE_VALID() macro, hurting readability.

^ permalink raw reply	[relevance 2%]

* [PATCH] repack: rewrite the shell script in C.
  @ 2013-08-13 19:23  4% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-08-13 19:23 UTC (permalink / raw)
  To: git, Matthieu.Moy, pclouds, iveqy, gitster, apelisse; +Cc: Stefan Beller

This is the beginning of the rewrite of the repacking.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                       |   2 +-
 builtin.h                      |   1 +
 builtin/repack.c               | 313 +++++++++++++++++++++++++++++++++++++++++
 contrib/examples/git-repack.sh | 194 +++++++++++++++++++++++++
 git-repack.sh                  | 194 -------------------------
 git.c                          |   1 +
 6 files changed, 510 insertions(+), 195 deletions(-)
 create mode 100644 builtin/repack.c
 create mode 100755 contrib/examples/git-repack.sh
 delete mode 100755 git-repack.sh

diff --git a/Makefile b/Makefile
index 3588ca1..69e5267 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -971,6 +970,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..bfec56d
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,313 @@
+/*
+ * The shell version was written by Linus Torvalds (2005) and many others.
+ * This is a translation into C by Stefan Beller (2013)
+ */
+
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+
+static const char * const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+static int delta_base_offset = 1; // enabled by default since 22c79eab (2008-06-25)
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	struct strbuf packtmpbuf = STRBUF_INIT;
+	/* todo: the files are not in a subdirectory, but only a subset in %s/pack, see disscussion */
+	strbuf_addf(&packtmpbuf, "%s/pack/.tmp-%d-pack", get_object_directory(), getpid());
+	remove_dir_recursively(&packtmpbuf, 0);
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix) {
+
+	int pack_everything = 0;
+	int pack_everything_but_loose = 0;
+	int delete_redundant = 0;
+	int unpack_unreachable = 0;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+	char *packdir, *packtmp;
+	const char *cmd_args[20];
+	int cmd_i = 0;
+	struct child_process cmd;
+
+	struct option builtin_repack_options[] = {
+		OPT_BOOL('a', "all", &pack_everything,
+				N_("pack everything in a single pack")),
+		OPT_BOOL('A', "all-but-loose", &pack_everything_but_loose,
+				N_("same as -a, and turn unreachable objects loose")),
+		OPT_BOOL('d', "delete-redundant", &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', "no-reuse-delta", &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', "no-reuse-object", &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_DATE(0, "unpack-unreachable", &unpack_unreachable,
+				N_("with -A, do not loosen objects older than this Packing constraints")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	packdir = mkpath("%s/pack", get_object_directory());
+	packtmp = mkpath("%s/.tmp-%d-pack", packdir, getpid());
+
+	struct strbuf packtmpbuf = STRBUF_INIT;
+	strbuf_addf(&packtmpbuf, "%s", packtmp);
+	remove_dir_recursively(&packtmpbuf, 0);
+
+	cmd_args[cmd_i++] = "pack-objects";
+	cmd_args[cmd_i++] = "--keep-true-parents";
+	cmd_args[cmd_i++] = "--honor-pack-keep";
+	cmd_args[cmd_i++] = "--non-empty";
+	cmd_args[cmd_i++] = "--all";
+	cmd_args[cmd_i++] = "--reflog";
+
+	if (pack_everything + pack_everything_but_loose == 0) {
+		cmd_args[cmd_i++] = "--unpacked";
+		cmd_args[cmd_i++] = "--incremental";
+	} else {
+		// todo:
+		// handle -a and -A option here.
+		// find all *.pack in pack dir:
+
+/*
+	if [ -d "$PACKDIR" ]; then
+		# cd into packdir and find all packs, sed will remove beginning ./ and ending .pack
+		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
+			| sed -e 's/^\.\///' -e 's/\.pack$//'`
+		do
+			if [ -e "$PACKDIR/$e.keep" ]; then
+				: keep
+				# do nothing
+			else
+				# add the pack to the existing list
+				existing="$existing $e"
+			fi
+		done
+		# -n string     True if the length of string is nonzero.
+		# -a and
+		if test -n "$existing" -a -n "$unpack_unreachable" -a \
+			-n "$remove_redundant"
+		then
+			# This may have arbitrary user arguments, so we
+			# have to protect it against whitespace splitting
+			# when it gets run as "pack-objects $args" later.
+			# Fortunately, we know it's an approxidate, so we
+			# can just use dots instead.
+			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
+		fi
+	fi
+*/
+	}
+
+	if (local)
+		cmd_args[cmd_i++] = "--local";
+
+	if (delta_base_offset)
+		cmd_args[cmd_i++] = "--delta-base-offset";
+
+	cmd_args[cmd_i++] = packtmp;
+	cmd_args[cmd_i] = NULL;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = cmd_args;
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	run_command(&cmd);
+
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_DUP;
+
+	char line[1024];
+	int counter = 0;
+	FILE *out = xfdopen(cmd.out, "r");
+	while (fgets(line, sizeof(line), out)) {
+		assert(strlen(line) == 41); // 40 chars for sha1 + '\n'
+		line[40] = '\0'; // remove '\n'
+		string_list_append(&names, line);
+		counter++;
+	}
+	if (!counter)
+		printf("Nothing new to pack.\n");
+	fclose(out);
+
+	char *fname, *fname_old;
+	fname = xmalloc(strlen(packdir) + 47); // 40 chars for the sha1
+	strcpy(fname, packdir);
+	strcpy(fname + strlen(packdir), "/");
+
+	fname_old = xmalloc(strlen(packdir) + 52); // 40 chars for the sha1
+	strcpy(fname_old, packdir);
+	strcpy(fname_old + strlen(packdir), "/");
+	char *exts[2] = {".idx", ".pack"};
+
+	int failed = 0;
+
+	struct string_list_item *item;
+	for_each_string_list_item(item, &names) {
+		int ext;
+		for (ext = 0; ext < 1; ext++) {
+			strcpy(fname + strlen(packdir) + 1, item->string);
+			strcpy(fname + strlen(packdir) + 41, exts[ext]);
+			if (!file_exists(fname))
+				continue;
+
+			strcpy(fname_old, packdir);
+			strcpy(fname_old + strlen(packdir), "/old-");
+			strcpy(fname_old + strlen(packdir) + 5, item->string);
+			strcpy(fname_old + strlen(packdir) + 45, exts[ext]);
+			if (file_exists(fname_old))
+				unlink(fname_old);
+
+			if (rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			string_list_append(&rollback, fname);
+		}
+		if (failed)
+			/* set to last element to break while loop */
+			item = names.items + names.nr;
+	}
+	if (failed) {
+		struct string_list rollback_failure;
+
+		for_each_string_list_item(item, &rollback) {
+			sprintf(fname, "%s/%s", packdir, item->string);
+			sprintf(fname_old, "%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+		}
+
+		if (rollback.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in $PACKDIR manually:\n");
+			for (i = 0; i < rollback.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback.items[i].string,
+					rollback.items[i].string);
+		}
+		exit(1);
+	}
+
+	// Now the ones with the same name are out of the way...
+	struct string_list fullbases = STRING_LIST_INIT_DUP;
+	for_each_string_list_item(item, &names) {
+		string_list_append(&fullbases, item->string);
+
+		sprintf(fname, "%s/pack-%s.pack", packdir, item->string);
+		sprintf(fname_old, "%s-%s.pack", packtmp, item->string);
+		chmod(fname_old, 0660);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+
+		sprintf(fname, "%s/pack-%s.idx", packdir, item->string);
+		sprintf(fname_old, "%s-%s.idx", packtmp, item->string);
+		chmod(fname_old, 0660); // todo, in shell there was "chmod a-w ..."
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		sprintf(fname, "%s/old-pack-%s.idx", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+
+		sprintf(fname, "%s/old-pack-%s.pack", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+	}
+
+	/* End of pack replacement. */
+	if (delete_redundant) {
+		// todo
+		/*
+			# We know $existing are all redundant.
+			if [ -n "$existing" ]
+			then
+				( cd "$PACKDIR" &&
+				  for e in $existing
+				  do
+					case " $fullbases " in
+					*" $e "*) ;;
+					*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
+					esac
+				  done
+				)
+			fi
+			git prune-packed ${GIT_QUIET:+-q}
+		*/
+	}
+
+	if (!no_update_server_info) {
+		cmd_i = 0;
+		cmd_args[cmd_i++] = "update-server-info";
+		cmd_args[cmd_i++] = NULL;
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+	return 0;
+}
+
diff --git a/contrib/examples/git-repack.sh b/contrib/examples/git-repack.sh
new file mode 100755
index 0000000..7579331
--- /dev/null
+++ b/contrib/examples/git-repack.sh
@@ -0,0 +1,194 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+#
+
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git repack [options]
+--
+a               pack everything in a single pack
+A               same as -a, and turn unreachable objects loose
+d               remove redundant packs, and run git-prune-packed
+f               pass --no-reuse-delta to git-pack-objects
+F               pass --no-reuse-object to git-pack-objects
+n               do not run git-update-server-info
+q,quiet         be quiet
+l               pass --local to git-pack-objects
+unpack-unreachable=  with -A, do not loosen objects older than this
+ Packing constraints
+window=         size of the window used for delta compression
+window-memory=  same as the above, but limit memory size instead of entries count
+depth=          limits the maximum delta depth
+max-pack-size=  maximum size of each packfile
+"
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
+no_update_info= all_into_one= remove_redundant= unpack_unreachable=
+local= no_reuse= extra=
+while test $# != 0
+do
+	case "$1" in
+	-n)	no_update_info=t ;;
+	-a)	all_into_one=t ;;
+	-A)	all_into_one=t
+		unpack_unreachable=--unpack-unreachable ;;
+	--unpack-unreachable)
+		unpack_unreachable="--unpack-unreachable=$2"; shift ;;
+	-d)	remove_redundant=t ;;
+	-q)	GIT_QUIET=t ;;
+	-f)	no_reuse=--no-reuse-delta ;;
+	-F)	no_reuse=--no-reuse-object ;;
+	-l)	local=--local ;;
+	--max-pack-size|--window|--window-memory|--depth)
+		extra="$extra $1=$2"; shift ;;
+	--) shift; break;;
+	*)	usage ;;
+	esac
+	shift
+done
+
+case "`git config --bool repack.usedeltabaseoffset || echo true`" in
+true)
+	extra="$extra --delta-base-offset" ;;
+esac
+
+PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
+PACKTMP="$PACKDIR/.tmp-$$-pack"
+rm -f "$PACKTMP"-*
+trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
+
+# There will be more repacking strategies to come...
+case ",$all_into_one," in
+,,)
+	args='--unpacked --incremental'
+	;;
+,t,)
+	args= existing=
+	if [ -d "$PACKDIR" ]; then
+		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
+			| sed -e 's/^\.\///' -e 's/\.pack$//'`
+		do
+			if [ -e "$PACKDIR/$e.keep" ]; then
+				: keep
+			else
+				existing="$existing $e"
+			fi
+		done
+		if test -n "$existing" -a -n "$unpack_unreachable" -a \
+			-n "$remove_redundant"
+		then
+			# This may have arbitrary user arguments, so we
+			# have to protect it against whitespace splitting
+			# when it gets run as "pack-objects $args" later.
+			# Fortunately, we know it's an approxidate, so we
+			# can just use dots instead.
+			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
+		fi
+	fi
+	;;
+esac
+
+mkdir -p "$PACKDIR" || exit
+
+args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
+names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
+	exit 1
+if [ -z "$names" ]; then
+	say Nothing new to pack.
+fi
+
+# Ok we have prepared all new packfiles.
+
+# First see if there are packs of the same name and if so
+# if we can move them out of the way (this can happen if we
+# repacked immediately after packing fully.
+rollback=
+failed=
+for name in $names
+do
+	for sfx in pack idx
+	do
+		file=pack-$name.$sfx
+		test -f "$PACKDIR/$file" || continue
+		rm -f "$PACKDIR/old-$file" &&
+		mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
+			failed=t
+			break
+		}
+		rollback="$rollback $file"
+	done
+	test -z "$failed" || break
+done
+
+# If renaming failed for any of them, roll the ones we have
+# already renamed back to their original names.
+if test -n "$failed"
+then
+	rollback_failure=
+	for file in $rollback
+	do
+		mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
+		rollback_failure="$rollback_failure $file"
+	done
+	if test -n "$rollback_failure"
+	then
+		echo >&2 "WARNING: Some packs in use have been renamed by"
+		echo >&2 "WARNING: prefixing old- to their name, in order to"
+		echo >&2 "WARNING: replace them with the new version of the"
+		echo >&2 "WARNING: file.  But the operation failed, and"
+		echo >&2 "WARNING: attempt to rename them back to their"
+		echo >&2 "WARNING: original names also failed."
+		echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
+		for file in $rollback_failure
+		do
+			echo >&2 "WARNING:   old-$file -> $file"
+		done
+	fi
+	exit 1
+fi
+
+# Now the ones with the same name are out of the way...
+fullbases=
+for name in $names
+do
+	fullbases="$fullbases pack-$name"
+	chmod a-w "$PACKTMP-$name.pack"
+	chmod a-w "$PACKTMP-$name.idx"
+	mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
+	mv -f "$PACKTMP-$name.idx"  "$PACKDIR/pack-$name.idx" ||
+	exit
+done
+
+# Remove the "old-" files
+for name in $names
+do
+	rm -f "$PACKDIR/old-pack-$name.idx"
+	rm -f "$PACKDIR/old-pack-$name.pack"
+done
+
+# End of pack replacement.
+
+if test "$remove_redundant" = t
+then
+	# We know $existing are all redundant.
+	if [ -n "$existing" ]
+	then
+		( cd "$PACKDIR" &&
+		  for e in $existing
+		  do
+			case " $fullbases " in
+			*" $e "*) ;;
+			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
+			esac
+		  done
+		)
+	fi
+	git prune-packed ${GIT_QUIET:+-q}
+fi
+
+case "$no_update_info" in
+t) : ;;
+*) git update-server-info ;;
+esac
diff --git a/git-repack.sh b/git-repack.sh
deleted file mode 100755
index 7579331..0000000
--- a/git-repack.sh
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-
-OPTIONS_KEEPDASHDASH=
-OPTIONS_SPEC="\
-git repack [options]
---
-a               pack everything in a single pack
-A               same as -a, and turn unreachable objects loose
-d               remove redundant packs, and run git-prune-packed
-f               pass --no-reuse-delta to git-pack-objects
-F               pass --no-reuse-object to git-pack-objects
-n               do not run git-update-server-info
-q,quiet         be quiet
-l               pass --local to git-pack-objects
-unpack-unreachable=  with -A, do not loosen objects older than this
- Packing constraints
-window=         size of the window used for delta compression
-window-memory=  same as the above, but limit memory size instead of entries count
-depth=          limits the maximum delta depth
-max-pack-size=  maximum size of each packfile
-"
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-no_update_info= all_into_one= remove_redundant= unpack_unreachable=
-local= no_reuse= extra=
-while test $# != 0
-do
-	case "$1" in
-	-n)	no_update_info=t ;;
-	-a)	all_into_one=t ;;
-	-A)	all_into_one=t
-		unpack_unreachable=--unpack-unreachable ;;
-	--unpack-unreachable)
-		unpack_unreachable="--unpack-unreachable=$2"; shift ;;
-	-d)	remove_redundant=t ;;
-	-q)	GIT_QUIET=t ;;
-	-f)	no_reuse=--no-reuse-delta ;;
-	-F)	no_reuse=--no-reuse-object ;;
-	-l)	local=--local ;;
-	--max-pack-size|--window|--window-memory|--depth)
-		extra="$extra $1=$2"; shift ;;
-	--) shift; break;;
-	*)	usage ;;
-	esac
-	shift
-done
-
-case "`git config --bool repack.usedeltabaseoffset || echo true`" in
-true)
-	extra="$extra --delta-base-offset" ;;
-esac
-
-PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
-PACKTMP="$PACKDIR/.tmp-$$-pack"
-rm -f "$PACKTMP"-*
-trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
-
-# There will be more repacking strategies to come...
-case ",$all_into_one," in
-,,)
-	args='--unpacked --incremental'
-	;;
-,t,)
-	args= existing=
-	if [ -d "$PACKDIR" ]; then
-		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
-			| sed -e 's/^\.\///' -e 's/\.pack$//'`
-		do
-			if [ -e "$PACKDIR/$e.keep" ]; then
-				: keep
-			else
-				existing="$existing $e"
-			fi
-		done
-		if test -n "$existing" -a -n "$unpack_unreachable" -a \
-			-n "$remove_redundant"
-		then
-			# This may have arbitrary user arguments, so we
-			# have to protect it against whitespace splitting
-			# when it gets run as "pack-objects $args" later.
-			# Fortunately, we know it's an approxidate, so we
-			# can just use dots instead.
-			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
-		fi
-	fi
-	;;
-esac
-
-mkdir -p "$PACKDIR" || exit
-
-args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
-names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
-	exit 1
-if [ -z "$names" ]; then
-	say Nothing new to pack.
-fi
-
-# Ok we have prepared all new packfiles.
-
-# First see if there are packs of the same name and if so
-# if we can move them out of the way (this can happen if we
-# repacked immediately after packing fully.
-rollback=
-failed=
-for name in $names
-do
-	for sfx in pack idx
-	do
-		file=pack-$name.$sfx
-		test -f "$PACKDIR/$file" || continue
-		rm -f "$PACKDIR/old-$file" &&
-		mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
-			failed=t
-			break
-		}
-		rollback="$rollback $file"
-	done
-	test -z "$failed" || break
-done
-
-# If renaming failed for any of them, roll the ones we have
-# already renamed back to their original names.
-if test -n "$failed"
-then
-	rollback_failure=
-	for file in $rollback
-	do
-		mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
-		rollback_failure="$rollback_failure $file"
-	done
-	if test -n "$rollback_failure"
-	then
-		echo >&2 "WARNING: Some packs in use have been renamed by"
-		echo >&2 "WARNING: prefixing old- to their name, in order to"
-		echo >&2 "WARNING: replace them with the new version of the"
-		echo >&2 "WARNING: file.  But the operation failed, and"
-		echo >&2 "WARNING: attempt to rename them back to their"
-		echo >&2 "WARNING: original names also failed."
-		echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
-		for file in $rollback_failure
-		do
-			echo >&2 "WARNING:   old-$file -> $file"
-		done
-	fi
-	exit 1
-fi
-
-# Now the ones with the same name are out of the way...
-fullbases=
-for name in $names
-do
-	fullbases="$fullbases pack-$name"
-	chmod a-w "$PACKTMP-$name.pack"
-	chmod a-w "$PACKTMP-$name.idx"
-	mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
-	mv -f "$PACKTMP-$name.idx"  "$PACKDIR/pack-$name.idx" ||
-	exit
-done
-
-# Remove the "old-" files
-for name in $names
-do
-	rm -f "$PACKDIR/old-pack-$name.idx"
-	rm -f "$PACKDIR/old-pack-$name.pack"
-done
-
-# End of pack replacement.
-
-if test "$remove_redundant" = t
-then
-	# We know $existing are all redundant.
-	if [ -n "$existing" ]
-	then
-		( cd "$PACKDIR" &&
-		  for e in $existing
-		  do
-			case " $fullbases " in
-			*" $e "*) ;;
-			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
-			esac
-		  done
-		)
-	fi
-	git prune-packed ${GIT_QUIET:+-q}
-fi
-
-case "$no_update_info" in
-t) : ;;
-*) git update-server-info ;;
-esac
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.rc2

^ permalink raw reply related	[relevance 4%]

* [ANNOUNCE] Git v1.8.4-rc3
@ 2013-08-13 22:09  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2013-08-13 22:09 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate Git v1.8.4-rc3 is now available for testing at
the usual places.

Things have calmed down on the 'master' front; we will still need to
revert one commit that killed "git stash" in a large directory with
a lot of cruft before the final, but other than that, everything
else should be pretty much the same as what we will see in the final
release.

The release tarballs are found at:

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

and their SHA-1 checksums are:

4017553f4543c00c392a299b6a67f8ca4ca5e325  git-1.8.4.rc3.tar.gz
1a3a6c6a59df7b60377a0ae86f04b8b0f09e45f4  git-htmldocs-1.8.4.rc3.tar.gz
19281d6fb14e66c5b215bad52e3857418052bfeb  git-manpages-1.8.4.rc3.tar.gz

The following public repositories all have a copy of the v1.8.4-rc3
tag and the master branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v1.8.4 Release Notes (draft)
========================

Backward compatibility notes (for Git 2.0)
------------------------------------------

When "git push [$there]" does not say what to push, we have used the
traditional "matching" semantics so far (all your branches were sent
to the remote as long as there already are branches of the same name
over there).  In Git 2.0, the default will change to the "simple"
semantics that pushes:

 - only the current branch to the branch with the same name, and only
   when the current branch is set to integrate with that remote
   branch, if you are pushing to the same remote as you fetch from; or

 - only the current branch to the branch with the same name, if you
   are pushing to a remote that is not where you usually fetch from.

Use the user preference configuration variable "push.default" to
change this.  If you are an old-timer who is used to the "matching"
semantics, you can set the variable to "matching" to keep the
traditional behaviour.  If you want to live in the future early, you
can set it to "simple" today without waiting for Git 2.0.

When "git add -u" (and "git add -A") is run inside a subdirectory and
does not specify which paths to add on the command line, it
will operate on the entire tree in Git 2.0 for consistency
with "git commit -a" and other commands.  There will be no
mechanism to make plain "git add -u" behave like "git add -u .".
Current users of "git add -u" (without a pathspec) should start
training their fingers to explicitly say "git add -u ."
before Git 2.0 comes.  A warning is issued when these commands are
run without a pathspec and when you have local changes outside the
current directory, because the behaviour in Git 2.0 will be different
from today's version in such a situation.

In Git 2.0, "git add <path>" will behave as "git add -A <path>", so
that "git add dir/" will notice paths you removed from the directory
and record the removal.  Versions before Git 2.0, including this
release, will keep ignoring removals, but the users who rely on this
behaviour are encouraged to start using "git add --ignore-removal <path>"
now before 2.0 is released.


Updates since v1.8.3
--------------------

Foreign interfaces, subsystems and ports.

 * Cygwin port has been updated for more recent Cygwin 1.7.

 * "git rebase -i" now honors --strategy and -X options.

 * Git-gui has been updated to its 0.18.0 version.

 * MediaWiki remote helper (in contrib/) has been updated to use the
   credential helper interface from Git.pm.

 * Update build for Cygwin 1.[57].  Torsten Bögershausen reports that
   this is fine with Cygwin 1.7 ($gmane/225824) so let's try moving it
   ahead.

 * The credential helper to talk to keychain on OS X (in contrib/) has
   been updated to kick in not just when talking http/https but also
   imap(s) and smtp.

 * Remote transport helper has been updated to report errors and
   maintain ref hierarchy used to keep track of its own state better.

 * With "export" remote-helper protocol, (1) a push that tries to
   update a remote ref whose name is different from the pushing side
   does not work yet, and (2) the helper may not know how to do
   --dry-run; these problematic cases are disabled for now.

 * git-remote-hg/bzr (in contrib/) updates.

 * git-remote-mw (in contrib/) hints users to check the certificate,
   when https:// connection failed.

 * git-remote-mw (in contrib/) adds a command to allow previewing the
   contents locally before pushing it out, when working with a
   MediaWiki remote.


UI, Workflows & Features

 * Sample "post-receive-email" hook script got an enhanced replacement
   "multimail" (in contrib/).

 * Also in contrib/ is a new "contacts" script that runs "git blame"
   to find out the people who may be interested in a set of changes.

 * "git clean" command learned an interactive mode.

 * The "--head" option to "git show-ref" was only to add "HEAD" to the
   list of candidate refs to be filtered by the usual rules
   (e.g. "--heads" that only show refs under refs/heads).  The meaning
   of the option has been changed to always show "HEAD" regardless of
   what filtering will be applied to any other ref.

   This is a backward incompatible change and might cause breakages to
   people's existing scripts.

 * "git show -s" was less discoverable than it should have been.  It
   now has a natural synonym "git show --no-patch".

 * "git check-mailmap" is a new command that lets you map usernames
   and e-mail addresses through the mailmap mechanism, just like many
   built-in commands do.

 * "git name-rev" learned to name an annotated tag object back to its
   tagname; "git name-rev $(git rev-parse v1.0.0)" gives "tags/v1.0.0",
   for example.

 * "git cat-file --batch-check=<format>" is added, primarily to allow
   on-disk footprint of objects in packfiles (often they are a lot
   smaller than their true size, when expressed as deltas) to be
   reported.

 * "git rebase [-i]" used to leave just "rebase" as its reflog messages
   for some operations. They have been reworded to be more informative.

 * In addition to the choice from "rebase, merge, or checkout-detach",
   "submodule update" can allow a custom command to be used in to
   update the working tree of submodules via the "submodule.*.update"
   configuration variable.

 * "git submodule update" can optionally clone the submodule
   repositories shallowly.

 * "git format-patch" learned "--from[=whom]" option, which sets the
   "From: " header to the specified person (or the person who runs the
   command, if "=whom" part is missing) and move the original author
   information to an in-body From: header as necessary.

 * The configuration variable "merge.ff" was cleary a tri-state to
   choose one from "favor fast-forward when possible", "always create
   a merge even when the history could fast-forward" and "do not
   create any merge, only update when the history fast-forwards", but
   the command line parser did not implement the usual convention of
   "last one wins, and command line overrides the configuration"
   correctly.

 * "gitweb" learned to optionally place extra links that point at the
   levels higher than the Gitweb pages themselves in the breadcrumbs,
   so that it can be used as part of a larger installation.

 * "git log --format=" now honors i18n.logoutputencoding configuration
   variable.

 * The "push.default=simple" mode of "git push" has been updated to
   behave like "current" without requiring a remote tracking
   information, when you push to a remote that is different from where
   you fetch from (i.e. a triangular workflow).

 * Having multiple "fixup!" on a line in the rebase instruction sheet
   did not work very well with "git rebase -i --autosquash".

 * "git log" learned the "--author-date-order" option, with which the
   output is topologically sorted and commits in parallel histories
   are shown intermixed together based on the author timestamp.

 * Various subcommands of "git submodule" refused to run from anywhere
   other than the top of the working tree of the superproject, but
   they have been taught to let you run from a subdirectory.

 * "git diff" learned a mode that ignores hunks whose change consists
   only of additions and removals of blank lines, which is the same as
   "diff -B" (ignore blank lines) of GNU diff.

 * "git rm" gives a single message followed by list of paths to report
   multiple paths that cannot be removed.

 * "git rebase" can be told with ":/look for this string" syntax commits
   to replay the changes onto and where the work to be replayed begins.

 * Many tutorials teach users to set "color.ui" to "auto" as the first
   thing after you set "user.name/email" to introduce yourselves to
   Git.  Now the variable defaults to "auto".

 * On Cygwin, "cygstart" is now recognised as a possible way to start
   a web browser (used in "help -w" and "instaweb" among others).

 * "git status" learned status.branch and status.short configuration
   variables to use --branch and --short options by default (override
   with --no-branch and --no-short options from the command line).

 * "git cmd <name>", when <name> happens to be a 40-hex string,
   directly uses the 40-hex string as an object name, even if a ref
   "refs/<some hierarchy>/<name>" exists.  This disambiguation order
   is unlikely to change, but we should warn about the ambiguity just
   like we warn when more than one refs/ hierarchies share the same
   name.

 * "git rebase" learned "--[no-]autostash" option to save local
   changes instead of refusing to run (to which people's normal
   response was to stash them and re-run).  This introduced a corner
   case breakage to "git am --abort" but it has been fixed.

 * Instead of typing four capital letters "HEAD", you can say "@" now,
   e.g. "git log @".

 * "check-ignore" (new feature since 1.8.2) has been updated to work
   more like "check-attr" over bidi-pipes.

 * "git describe" learned "--first-parent" option to limit its closest
   tagged commit search to the first-parent chain.

 * "git merge foo" that might have meant "git merge origin/foo" is
   diagnosed with a more informative error message.

 * "git log -L<line>,<range>:<filename>" has been added.  This may
   still have leaks and rough edges, though.

 * We used the approxidate() parser for "--expire=<timestamp>" options
   of various commands, but it is better to treat --expire=all and
   --expire=now a bit more specially than using the current timestamp.
   "git gc" and "git reflog" have been updated with a new parsing
   function for expiry dates.

 * Updates to completion (both bash and zsh) helpers.

 * The behaviour of the "--chain-reply-to" option of "git send-email"
   have changed at 1.7.0, and we added a warning/advice message to
   help users adjust to the new behaviour back then, but we kept it
   around for too long.  The message has finally been removed.

 * "git fetch origin master" unlike "git fetch origin" or "git fetch"
   did not update "refs/remotes/origin/master"; this was an early
   design decision to keep the update of remote tracking branches
   predictable, but in practice it turns out that people find it more
   convenient to opportunistically update them whenever we have a
   chance, and we have been updating them when we run "git push" which
   already breaks the original "predictability" anyway.

 * The configuration variable core.checkstat was advertised in the
   documentation but the code expected core.statinfo instead.
   For now, we accept both core.checkstat and core.statinfo, but the
   latter will be removed in the longer term.


Performance, Internal Implementation, etc.

 * On Cygwin, we used to use our own lstat(2) emulation that is
   allegedly faster than the platform one in codepaths where some of
   the information it returns did not matter, but it started to bite
   us in a few codepaths where the trick it uses to cheat does show
   breakages. This emulation has been removed and we use the native
   lstat(2) emulation supplied by Cygwin now.

 * The function attributes extensions are used to catch mistakes in
   use of our own variadic functions that use NULL sentinel at the end
   (i.e. like execl(3)) and format strings (i.e. like printf(3)).

 * The code to allow configuration data to be read from in-tree blob
   objects is in.  This may help working in a bare repository and
   submodule updates.

 * Fetching between repositories with many refs employed O(n^2)
   algorithm to match up the common objects, which has been corrected.

 * The original way to specify remote repository using .git/branches/
   used to have a nifty feature.  The code to support the feature was
   still in a function but the caller was changed not to call it 5
   years ago, breaking that feature and leaving the supporting code
   unreachable.  The dead code has been removed.

 * "git pack-refs" that races with new ref creation or deletion have
   been susceptible to lossage of refs under right conditions, which
   has been tightened up.

 * We read loose and packed rerferences in two steps, but after
   deciding to read a loose ref but before actually opening it to read
   it, another process racing with us can unlink it, which would cause
   us to barf.  The codepath has been updated to retry when such a
   race is detected, instead of outright failing.

 * Uses of the platform fnmatch(3) function (many places in the code,
   matching pathspec, .gitignore and .gitattributes to name a few)
   have been replaced with wildmatch, allowing "foo/**/bar" that would
   match foo/bar, foo/a/bar, foo/a/b/bar, etc.

 * Memory ownership and lifetime rules for what for-each-ref feeds to
   its callbacks have been clarified (in short, "you do not own it, so
   make a copy if you want to keep it").

 * The revision traversal logic to improve culling of irrelevant
   parents while traversing a mergy history has been updated.

 * Some leaks in unpack-trees (used in merge, cherry-pick and other
   codepaths) have been plugged.

 * The codepath to read from marks files in fast-import/export did not
   have to accept anything but 40-hex representation of the object
   name.  Further, fast-export did not need full in-core object
   representation to have parsed wen reading from them.  These
   codepaths have been optimized by taking advantage of these access
   patterns.

 * Object lookup logic, when the object hashtable starts to become
   crowded, has been optimized.

 * When TEST_OUTPUT_DIRECTORY setting is used, it was handled somewhat
   inconsistently between the test framework and t/Makefile, and logic
   to summarize the results looked at a wrong place.

 * "git clone" uses a lighter-weight implementation when making sure
   that the history behind refs are complete.

 * Many warnings from sparse source checker in compat/ area has been
   squelched.

 * The code to reading and updating packed-refs file has been updated,
   correcting corner case bugs.


Also contains various documentation updates and code clean-ups.


Fixes since v1.8.3
------------------

Unless otherwise noted, all the fixes since v1.8.3 in the maintenance
track are contained in this release (see release notes to them for
details).

 * Newer Net::SMTP::SSL module does not want the user programs to use
   the default behaviour to let server certificate go without
   verification, so by default enable the verification with a
   mechanism to turn it off if needed.
   (merge 35035bb rr/send-email-ssl-verify later to maint).

 * When "git" is spawned in such a way that any of the low 3 file
   descriptors is closed, our first open() may yield file descriptor 2,
   and writing error message to it would screw things up in a big way.
   (merge a11c396 tr/protect-low-3-fds later to maint).

 * The mailmap mechanism unnecessarily downcased the e-mail addresses
   in the output, and also ignored the human name when it is a single
   character name.
   (merge bd23794 jc/mailmap-case-insensitivity later to maint).

 * In two places we did not check return value (expected to be a file
   descriptor) correctly.
   (merge a77f106 tr/fd-gotcha-fixes later to maint).

 * Logic to auto-detect character encodings in the commit log message
   did not reject overlong and invalid UTF-8 characters.
   (merge 81050ac bc/commit-invalid-utf8 later to maint).

 * Pass port number as a separate argument when "send-email" initializes
   Net::SMTP, instead of as a part of the hostname, i.e. host:port.
   This allows GSSAPI codepath to match with the hostname given.
   (merge 1a741bf bc/send-email-use-port-as-separate-param later to maint).

 * "git diff" refused to even show difference when core.safecrlf is
   set to true (i.e. error out) and there are offending lines in the
   working tree files.
   (merge 5430bb2 jc/maint-diff-core-safecrlf later to maint).

 * A test that should have failed but didn't revealed a bug that needs
   to be corrected.
   (merge 94d75d1 jc/t1512-fix later to maint).

 * An overlong path to a .git directory may have overflown the
   temporary path buffer used to create a name for lockfiles.
   (merge 2fbd4f9 mh/maint-lockfile-overflow later to maint).

 * Invocations of "git checkout" used internally by "git rebase" were
   counted as "checkout", and affected later "git checkout -" to the
   the user to an unexpected place.
   (merge 3bed291 rr/rebase-checkout-reflog later to maint).

 * "git stash save", when your local change turns a tracked file into
   a directory, has to remove files in that directory in order to
   revert your working tree to a pristine state.  This will lose
   untracked files in such a directory, and the command now requires
   you to "--force" it.

 * The configuration variable column.ui was poorly documented.
   (merge 5e62cc1 rr/column-doc later to maint).

 * "git name-rev --refs=tags/v*" were forbidden, which was a bit
   inconvenient (you had to give a pattern to match refs fully, like
   --refs=refs/tags/v*).
   (merge 98c5c4a nk/name-rev-abbreviated-refs later to maint).

 * "git apply" parsed patches that add new files, generated by
   programs other than Git, incorrectly.  This is an old breakage in
   v1.7.11 and will need to be merged down to the maintanance tracks.

 * Older cURL wanted piece of memory we call it with to be stable, but
   we updated the auth material after handing it to a call.

 * "git pull" into nothing trashed "local changes" that were in the
   index, and this avoids it.

 * Many "git submodule" operations do not work on a submodule at a
   path whose name is not in ASCII.

 * "cherry-pick" had a small leak in an error codepath.

 * Logic used by git-send-email to suppress cc mishandled names like
   "A U. Thor" <author@example.xz>, where the human readable part
   needs to be quoted (the user input may not have the double quotes
   around the name, and comparison was done between quoted and
   unquoted strings).  It also mishandled names that need RFC2047
   quoting.

 * Call to discard_cache/discard_index (used when we use different
   contents of the index in-core, in many operations like commit,
   apply, and merge) used to leak memory that held the array of index
   entries, which has been plugged.
   (merge a0fc4db rs/discard-index-discard-array later to maint).

 * "gitweb" forgot to clear a global variable $search_regexp upon each
   request, mistakenly carrying over the previous search to a new one
   when used as a persistent CGI.

 * The wildmatch engine did not honor WM_CASEFOLD option correctly.

 * "git log -c --follow $path" segfaulted upon hitting the commit that
   renamed the $path being followed.

 * When a reflog notation is used for implicit "current branch", we
   did not say which branch and worse said "branch ''".

 * "difftool --dir-diff" did not copy back changes made by the
   end-user in the diff tool backend to the working tree in some
   cases.

 * "git push $there HEAD:branch" did not resolve HEAD early enough, so
   it was easy to flip it around while push is still going on and push
   out a branch that the user did not originally intended when the
   command was started.

 * The bash prompt code (in contrib/) displayed the name of the branch
   being rebased when "rebase -i/-m/-p" modes are in use, but not the
   plain vanilla "rebase".

 * Handling of negative exclude pattern for directories "!dir" was
   broken in the update to v1.8.3.

 * zsh prompt script that borrowed from bash prompt script did not
   work due to slight differences in array variable notation between
   these two shells.

 * An entry for "file://" scheme in the enumeration of URL types Git
   can take in the HTML documentation was made into a clickable link
   by mistake.

 * "git push --[no-]verify" was not documented.

 * Stop installing the git-remote-testpy script that is only used for
   testing.

 * "git commit --allow-empty-message -m ''" should not start an
   editor.

 * "git merge @{-1}~22" was rewritten to "git merge frotz@{1}~22"
   incorrectly when your previous branch was "frotz" (it should be
   rewritten to "git merge frotz~22" instead).

 * "git diff -c -p" was not showing a deleted line from a hunk when
   another hunk immediately begins where the earlier one ends.

 * "git log --ancestry-path A...B" did not work as expected, as it did
   not pay attention to the fact that the merge base between A and B
   was the bottom of the range being specified.

 * Mac OS X does not like to write(2) more than INT_MAX number of
   bytes; work it around by chopping write(2) into smaller pieces.

 * Newer MacOS X encourages the programs to compile and link with
   their CommonCrypto, not with OpenSSL.

 * "git clone foo/bar:baz" cannot be a request to clone from a remote
   over git-over-ssh specified in the scp style.  This case is now
   detected and clones from a local repository at "foo/bar:baz".

 * When $HOME is misconfigured to point at an unreadable directory, we
   used to complain and die. Loosen the check.

 * "git subtree" (in contrib/) had one codepath with loose error
   checks to lose data at the remote side.

 * "git fetch" into a shallow repository from a repository that does
   not know about the shallow boundary commits (e.g. a different fork
   from the repository the current shallow repository was cloned from)
   did not work correctly.

 * "git checkout foo" DWIMs the intended "upstream" and turns it into
   "git checkout -t -b foo remotes/origin/foo". This codepath has been
   updated to correctly take existing remote definitions into account.

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

Changes since v1.8.4-rc2 are as follows:

Eric Sunshine (1):
      parse-options: fix clang opterror() -Wunused-value warning

Jean-Noel Avila (2):
      l10n: fr.po: 821/2112 messages translated
      l10n: Add reference for french translation team

Jiang Xin (2):
      l10n: git.pot: v1.8.4 round 2 (5 new, 3 removed)
      l10n: zh_CN.po: translate 5 messages (2135t0f0u)

Junio C Hamano (2):
      .mailmap: update long-lost friends with multiple defunct addresses
      Git 1.8.4-rc3

Matthieu Moy (1):
      git-remote-mediawiki: ignore generated git-mw

Peter Krefting (1):
      l10n: Update Swedish translation (2135t0f0u)

Phil Hord (1):
      t/t7407: fix two typos in submodule tests

Ralf Thielow (3):
      l10n: de.po: switch from pure German to German+English
      l10n: de.po: translate 99 new messages
      l10n: de.po: translate 5 messages

Stefan Beller (2):
      .mailmap: fixup entries
      .mailmap: Combine more (name, email) to individual persons

Tran Ngoc Quan (1):
      l10n: vi.po(2135t): v1.8.4 round 2

Wieland Hoffmann (1):
      l10n: de.po: Fix a typo

^ permalink raw reply	[relevance 2%]

* [RFC PATCH] repack: rewrite the shell script in C.
  @ 2013-08-14 16:27  3% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-08-14 16:27 UTC (permalink / raw)
  To: git, Matthieu.Moy, pclouds, iveqy, gitster, apelisse; +Cc: Stefan Beller

* Suggestions by Matthieu Moy have been included.
* I think it is completed apart from small todos and bugfixes.
* breaks the test suite, first breakage is t5301 (gc, sliding window)

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                       |   2 +-
 builtin.h                      |   1 +
 builtin/repack.c               | 410 +++++++++++++++++++++++++++++++++++++++++
 contrib/examples/git-repack.sh | 194 +++++++++++++++++++
 git-repack.sh                  | 194 -------------------
 git.c                          |   1 +
 6 files changed, 607 insertions(+), 195 deletions(-)
 create mode 100644 builtin/repack.c
 create mode 100755 contrib/examples/git-repack.sh
 delete mode 100755 git-repack.sh

diff --git a/Makefile b/Makefile
index ef442eb..4ec5bbe 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -972,6 +971,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..d39c34e
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,410 @@
+/*
+ * The shell version was written by Linus Torvalds (2005) and many others.
+ * This is a translation into C by Stefan Beller (2013)
+ */
+
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+/* enabled by default since 22c79eab (2008-06-25) */
+static int delta_base_offset = 1;
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+static void remove_temporary_files() {
+	DIR *dir;
+	struct dirent *e;
+	char *prefix, *path, *fname;
+
+	prefix = xmalloc(strlen(".tmp-10000-pack") + 1);
+	sprintf(prefix, ".tmp-%d-pack", getpid());
+
+	path = xmalloc(strlen(get_object_directory()) + strlen("/pack") + 1);
+	sprintf(path, "%s/pack", get_object_directory());
+
+	fname = xmalloc(strlen(path) + strlen("/")
+		+ strlen(prefix) + strlen("/")
+		+ 40 + strlen(".pack") + 1);
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!prefixcmp(e->d_name, prefix)) {
+			sprintf(fname, "%s/%s", path, e->d_name);
+			unlink(fname);
+		}
+	}
+	free(fname);
+	free(prefix);
+	free(path);
+	closedir(dir);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+void get_pack_sha1_list(char *packdir, struct string_list *sha1_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *path, *suffix;
+
+	path = xmalloc(strlen(get_object_directory()) + strlen("/pack") + 1);
+	sprintf(path, "%s/pack", get_object_directory());
+
+	suffix = ".pack";
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!suffixcmp(e->d_name, suffix)) {
+			char buf[255], *sha1;
+			strcpy(buf, e->d_name);
+			buf[strlen(e->d_name) - strlen(suffix)] = '\0';
+			sha1 = &buf[strlen(e->d_name) - strlen(suffix) - 40];
+			string_list_append(sha1_list, sha1);
+		}
+	}
+	free(path);
+	closedir(dir);
+}
+
+void remove_pack(char *path, char* sha1)
+{
+	DIR *dir;
+	struct dirent *e;
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+
+		char *sha_begin, *sha_end;
+		sha_end = e->d_name + strlen(e->d_name);
+		while (sha_end > e->d_name && *sha_end != '.')
+			sha_end--;
+
+		/* do not touch files not ending in .pack, .idx or .keep */
+		if (strcmp(sha_end, ".pack") &&
+			strcmp(sha_end, ".idx") &&
+			strcmp(sha_end, ".keep"))
+			continue;
+
+		sha_begin = sha_end - 40;
+
+		if (sha_begin >= e->d_name && !strncmp(sha_begin, sha1, 40)) {
+			char *fname;
+			fname = xmalloc(strlen(path) + 1 + strlen(e->d_name));
+			sprintf(fname, "%s/%s", path, e->d_name);
+			unlink(fname);
+			/*TODO: free(fname); fails here sometimes, needs investigation*/
+			break;
+		}
+	}
+	closedir(dir);
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix) {
+
+	int pack_everything = 0;
+	int pack_everything_but_loose = 0;
+	int delete_redundant = 0;
+	unsigned long unpack_unreachable = 0;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+	char *packdir, *packtmp;
+	const char *cmd_args[20];
+	int cmd_i = 0;
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	struct stat statbuffer;
+	char window_str[64], window_mem_str[64], depth_str[64], max_pack_size_str[64];
+
+	struct option builtin_repack_options[] = {
+		OPT_BOOL('a', "all", &pack_everything,
+				N_("pack everything in a single pack")),
+		OPT_BOOL('A', "all-but-loose", &pack_everything_but_loose,
+				N_("same as -a, and turn unreachable objects loose")),
+		OPT_BOOL('d', "delete-redundant", &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', "no-reuse-delta", &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', "no-reuse-object", &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_DATE(0, "unpack-unreachable", &unpack_unreachable,
+				N_("with -A, do not loosen objects older than this Packing constraints")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	packdir = mkpath("%s/pack", get_object_directory());
+	packtmp = xmalloc(strlen(packdir) + strlen("/.tmp-10000-pack") + 1);
+	sprintf(packtmp, "%s/.tmp-%d-pack", packdir, getpid());
+
+	remove_temporary_files();
+
+	cmd_args[cmd_i++] = "pack-objects";
+	cmd_args[cmd_i++] = "--keep-true-parents";
+	cmd_args[cmd_i++] = "--honor-pack-keep";
+	cmd_args[cmd_i++] = "--non-empty";
+	cmd_args[cmd_i++] = "--all";
+	cmd_args[cmd_i++] = "--reflog";
+
+	if (window) {
+		sprintf(window_str, "--window=%u", window);
+		cmd_args[cmd_i++] = window_str;
+	}
+	if (window_memory) {
+		sprintf(window_mem_str, "--window-memory=%u", window_memory);
+		cmd_args[cmd_i++] = window_str;
+	}
+	if (depth) {
+		sprintf(depth_str, "--depth=%u", depth);
+		cmd_args[cmd_i++] = depth_str;
+	}
+	if (max_pack_size) {
+		sprintf(max_pack_size_str, "--max_pack_size=%u", max_pack_size);
+		cmd_args[cmd_i++] = max_pack_size_str;
+	}
+
+	if (pack_everything + pack_everything_but_loose == 0) {
+		cmd_args[cmd_i++] = "--unpacked";
+		cmd_args[cmd_i++] = "--incremental";
+	} else {
+		if (pack_everything_but_loose)
+			cmd_args[cmd_i++] = "--unpack-unreachable";
+
+		struct string_list sha1_list = STRING_LIST_INIT_DUP;
+		get_pack_sha1_list(packdir, &sha1_list);
+		for_each_string_list_item(item, &sha1_list) {
+			char *fname;
+			fname = xmalloc(strlen(packdir) + strlen("/") + 40 + strlen(".keep"));
+			sprintf(fname, "%s/%s.keep", packdir, item->string);
+			if (stat(fname, &statbuffer) && S_ISREG(statbuffer.st_mode)) {
+				/* when the keep file is there, we're ignoring that pack */
+			} else {
+				string_list_append(&existing_packs, item->string);
+			}
+		}
+
+		if (existing_packs.nr && unpack_unreachable && delete_redundant) {
+			/*
+			 * TODO: convert unpack_unreachable (being time since epoch)
+			 * to an aproxidate again
+			 */
+			cmd_args[cmd_i++] = "--unpack-unreachable=$DATE";
+		}
+	}
+
+	if (local)
+		cmd_args[cmd_i++] = "--local";
+
+	if (delta_base_offset)
+		cmd_args[cmd_i++] = "--delta-base-offset";
+
+	cmd_args[cmd_i++] = packtmp;
+	cmd_args[cmd_i] = NULL;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = cmd_args;
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	run_command(&cmd);
+
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_DUP;
+
+	char line[1024];
+	int counter = 0;
+	FILE *out = xfdopen(cmd.out, "r");
+	while (fgets(line, sizeof(line), out)) {
+		/* a line consists of 40 hex chars + '\n' */
+		assert(strlen(line) == 41);
+		line[40] = '\0';
+		string_list_append(&names, line);
+		counter++;
+	}
+	if (!counter)
+		printf("Nothing new to pack.\n");
+	fclose(out);
+
+	char *fname, *fname_old;
+	fname = xmalloc(strlen(packdir) + strlen("/old-pack-") + 40 + strlen(".pack") + 1);
+	strcpy(fname, packdir);
+	strcpy(fname + strlen(packdir), "/");
+
+	fname_old = xmalloc(strlen(packdir) + strlen("/old-pack-") + 40 + strlen(".pack") + 1);
+	strcpy(fname_old, packdir);
+	strcpy(fname_old + strlen(packdir), "/");
+	char *exts[2] = {".idx", ".pack"};
+
+	int failed = 0;
+
+	for_each_string_list_item(item, &names) {
+		int ext;
+		for (ext = 0; ext < 1; ext++) {
+			strcpy(fname + strlen(packdir) + 1, item->string);
+			strcpy(fname + strlen(packdir) + 41, exts[ext]);
+			if (!file_exists(fname))
+				continue;
+
+			strcpy(fname_old, packdir);
+			strcpy(fname_old + strlen(packdir), "/old-");
+			strcpy(fname_old + strlen(packdir) + 5, item->string);
+			strcpy(fname_old + strlen(packdir) + 45, exts[ext]);
+			if (file_exists(fname_old))
+				unlink(fname_old);
+
+			if (rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			string_list_append(&rollback, fname);
+		}
+		if (failed)
+			/* set to last element to break while loop */
+			item = names.items + names.nr;
+	}
+	if (failed) {
+		struct string_list rollback_failure;
+
+		for_each_string_list_item(item, &rollback) {
+			sprintf(fname, "%s/%s", packdir, item->string);
+			sprintf(fname_old, "%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+		}
+
+		if (rollback.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in $PACKDIR manually:\n");
+			for (i = 0; i < rollback.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback.items[i].string,
+					rollback.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	struct string_list fullbases = STRING_LIST_INIT_DUP;
+	for_each_string_list_item(item, &names) {
+		string_list_append(&fullbases, item->string);
+
+		sprintf(fname, "%s/pack-%s.pack", packdir, item->string);
+		sprintf(fname_old, "%s-%s.pack", packtmp, item->string);
+		stat(fname_old, &statbuffer);
+		statbuffer.st_mode &= ~S_IWOTH;
+		chmod(fname_old, statbuffer.st_mode);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+
+		sprintf(fname, "%s/pack-%s.idx", packdir, item->string);
+		sprintf(fname_old, "%s-%s.idx", packtmp, item->string);
+		stat(fname_old, &statbuffer);
+		statbuffer.st_mode &= ~S_IWOTH;
+		chmod(fname_old, statbuffer.st_mode);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		sprintf(fname, "%s/old-pack-%s.idx", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+
+		sprintf(fname, "%s/old-pack-%s.pack", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+	}
+
+	/* End of pack replacement. */
+	if (delete_redundant) {
+		sort_string_list(&fullbases);
+		fname = xmalloc(strlen(packtmp) + strlen("/") + 40 + strlen(".pack") + 1);
+		for_each_string_list_item(item, &existing_packs) {
+			if (!string_list_has_string(&fullbases, item->string))
+				remove_pack(packdir, item->string);
+		}
+		free(fname);
+		cmd_i = 0;
+		cmd_args[cmd_i++] = "prune-packed";
+		cmd_args[cmd_i++] = NULL;
+		/* TODO: pass argument: ${GIT_QUIET:+-q} */
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+
+	if (!no_update_server_info) {
+		cmd_i = 0;
+		cmd_args[cmd_i++] = "update-server-info";
+		cmd_args[cmd_i++] = NULL;
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+	return 0;
+}
+
diff --git a/contrib/examples/git-repack.sh b/contrib/examples/git-repack.sh
new file mode 100755
index 0000000..7579331
--- /dev/null
+++ b/contrib/examples/git-repack.sh
@@ -0,0 +1,194 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+#
+
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git repack [options]
+--
+a               pack everything in a single pack
+A               same as -a, and turn unreachable objects loose
+d               remove redundant packs, and run git-prune-packed
+f               pass --no-reuse-delta to git-pack-objects
+F               pass --no-reuse-object to git-pack-objects
+n               do not run git-update-server-info
+q,quiet         be quiet
+l               pass --local to git-pack-objects
+unpack-unreachable=  with -A, do not loosen objects older than this
+ Packing constraints
+window=         size of the window used for delta compression
+window-memory=  same as the above, but limit memory size instead of entries count
+depth=          limits the maximum delta depth
+max-pack-size=  maximum size of each packfile
+"
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
+no_update_info= all_into_one= remove_redundant= unpack_unreachable=
+local= no_reuse= extra=
+while test $# != 0
+do
+	case "$1" in
+	-n)	no_update_info=t ;;
+	-a)	all_into_one=t ;;
+	-A)	all_into_one=t
+		unpack_unreachable=--unpack-unreachable ;;
+	--unpack-unreachable)
+		unpack_unreachable="--unpack-unreachable=$2"; shift ;;
+	-d)	remove_redundant=t ;;
+	-q)	GIT_QUIET=t ;;
+	-f)	no_reuse=--no-reuse-delta ;;
+	-F)	no_reuse=--no-reuse-object ;;
+	-l)	local=--local ;;
+	--max-pack-size|--window|--window-memory|--depth)
+		extra="$extra $1=$2"; shift ;;
+	--) shift; break;;
+	*)	usage ;;
+	esac
+	shift
+done
+
+case "`git config --bool repack.usedeltabaseoffset || echo true`" in
+true)
+	extra="$extra --delta-base-offset" ;;
+esac
+
+PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
+PACKTMP="$PACKDIR/.tmp-$$-pack"
+rm -f "$PACKTMP"-*
+trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
+
+# There will be more repacking strategies to come...
+case ",$all_into_one," in
+,,)
+	args='--unpacked --incremental'
+	;;
+,t,)
+	args= existing=
+	if [ -d "$PACKDIR" ]; then
+		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
+			| sed -e 's/^\.\///' -e 's/\.pack$//'`
+		do
+			if [ -e "$PACKDIR/$e.keep" ]; then
+				: keep
+			else
+				existing="$existing $e"
+			fi
+		done
+		if test -n "$existing" -a -n "$unpack_unreachable" -a \
+			-n "$remove_redundant"
+		then
+			# This may have arbitrary user arguments, so we
+			# have to protect it against whitespace splitting
+			# when it gets run as "pack-objects $args" later.
+			# Fortunately, we know it's an approxidate, so we
+			# can just use dots instead.
+			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
+		fi
+	fi
+	;;
+esac
+
+mkdir -p "$PACKDIR" || exit
+
+args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
+names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
+	exit 1
+if [ -z "$names" ]; then
+	say Nothing new to pack.
+fi
+
+# Ok we have prepared all new packfiles.
+
+# First see if there are packs of the same name and if so
+# if we can move them out of the way (this can happen if we
+# repacked immediately after packing fully.
+rollback=
+failed=
+for name in $names
+do
+	for sfx in pack idx
+	do
+		file=pack-$name.$sfx
+		test -f "$PACKDIR/$file" || continue
+		rm -f "$PACKDIR/old-$file" &&
+		mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
+			failed=t
+			break
+		}
+		rollback="$rollback $file"
+	done
+	test -z "$failed" || break
+done
+
+# If renaming failed for any of them, roll the ones we have
+# already renamed back to their original names.
+if test -n "$failed"
+then
+	rollback_failure=
+	for file in $rollback
+	do
+		mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
+		rollback_failure="$rollback_failure $file"
+	done
+	if test -n "$rollback_failure"
+	then
+		echo >&2 "WARNING: Some packs in use have been renamed by"
+		echo >&2 "WARNING: prefixing old- to their name, in order to"
+		echo >&2 "WARNING: replace them with the new version of the"
+		echo >&2 "WARNING: file.  But the operation failed, and"
+		echo >&2 "WARNING: attempt to rename them back to their"
+		echo >&2 "WARNING: original names also failed."
+		echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
+		for file in $rollback_failure
+		do
+			echo >&2 "WARNING:   old-$file -> $file"
+		done
+	fi
+	exit 1
+fi
+
+# Now the ones with the same name are out of the way...
+fullbases=
+for name in $names
+do
+	fullbases="$fullbases pack-$name"
+	chmod a-w "$PACKTMP-$name.pack"
+	chmod a-w "$PACKTMP-$name.idx"
+	mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
+	mv -f "$PACKTMP-$name.idx"  "$PACKDIR/pack-$name.idx" ||
+	exit
+done
+
+# Remove the "old-" files
+for name in $names
+do
+	rm -f "$PACKDIR/old-pack-$name.idx"
+	rm -f "$PACKDIR/old-pack-$name.pack"
+done
+
+# End of pack replacement.
+
+if test "$remove_redundant" = t
+then
+	# We know $existing are all redundant.
+	if [ -n "$existing" ]
+	then
+		( cd "$PACKDIR" &&
+		  for e in $existing
+		  do
+			case " $fullbases " in
+			*" $e "*) ;;
+			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
+			esac
+		  done
+		)
+	fi
+	git prune-packed ${GIT_QUIET:+-q}
+fi
+
+case "$no_update_info" in
+t) : ;;
+*) git update-server-info ;;
+esac
diff --git a/git-repack.sh b/git-repack.sh
deleted file mode 100755
index 7579331..0000000
--- a/git-repack.sh
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-
-OPTIONS_KEEPDASHDASH=
-OPTIONS_SPEC="\
-git repack [options]
---
-a               pack everything in a single pack
-A               same as -a, and turn unreachable objects loose
-d               remove redundant packs, and run git-prune-packed
-f               pass --no-reuse-delta to git-pack-objects
-F               pass --no-reuse-object to git-pack-objects
-n               do not run git-update-server-info
-q,quiet         be quiet
-l               pass --local to git-pack-objects
-unpack-unreachable=  with -A, do not loosen objects older than this
- Packing constraints
-window=         size of the window used for delta compression
-window-memory=  same as the above, but limit memory size instead of entries count
-depth=          limits the maximum delta depth
-max-pack-size=  maximum size of each packfile
-"
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-no_update_info= all_into_one= remove_redundant= unpack_unreachable=
-local= no_reuse= extra=
-while test $# != 0
-do
-	case "$1" in
-	-n)	no_update_info=t ;;
-	-a)	all_into_one=t ;;
-	-A)	all_into_one=t
-		unpack_unreachable=--unpack-unreachable ;;
-	--unpack-unreachable)
-		unpack_unreachable="--unpack-unreachable=$2"; shift ;;
-	-d)	remove_redundant=t ;;
-	-q)	GIT_QUIET=t ;;
-	-f)	no_reuse=--no-reuse-delta ;;
-	-F)	no_reuse=--no-reuse-object ;;
-	-l)	local=--local ;;
-	--max-pack-size|--window|--window-memory|--depth)
-		extra="$extra $1=$2"; shift ;;
-	--) shift; break;;
-	*)	usage ;;
-	esac
-	shift
-done
-
-case "`git config --bool repack.usedeltabaseoffset || echo true`" in
-true)
-	extra="$extra --delta-base-offset" ;;
-esac
-
-PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
-PACKTMP="$PACKDIR/.tmp-$$-pack"
-rm -f "$PACKTMP"-*
-trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
-
-# There will be more repacking strategies to come...
-case ",$all_into_one," in
-,,)
-	args='--unpacked --incremental'
-	;;
-,t,)
-	args= existing=
-	if [ -d "$PACKDIR" ]; then
-		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
-			| sed -e 's/^\.\///' -e 's/\.pack$//'`
-		do
-			if [ -e "$PACKDIR/$e.keep" ]; then
-				: keep
-			else
-				existing="$existing $e"
-			fi
-		done
-		if test -n "$existing" -a -n "$unpack_unreachable" -a \
-			-n "$remove_redundant"
-		then
-			# This may have arbitrary user arguments, so we
-			# have to protect it against whitespace splitting
-			# when it gets run as "pack-objects $args" later.
-			# Fortunately, we know it's an approxidate, so we
-			# can just use dots instead.
-			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
-		fi
-	fi
-	;;
-esac
-
-mkdir -p "$PACKDIR" || exit
-
-args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
-names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
-	exit 1
-if [ -z "$names" ]; then
-	say Nothing new to pack.
-fi
-
-# Ok we have prepared all new packfiles.
-
-# First see if there are packs of the same name and if so
-# if we can move them out of the way (this can happen if we
-# repacked immediately after packing fully.
-rollback=
-failed=
-for name in $names
-do
-	for sfx in pack idx
-	do
-		file=pack-$name.$sfx
-		test -f "$PACKDIR/$file" || continue
-		rm -f "$PACKDIR/old-$file" &&
-		mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
-			failed=t
-			break
-		}
-		rollback="$rollback $file"
-	done
-	test -z "$failed" || break
-done
-
-# If renaming failed for any of them, roll the ones we have
-# already renamed back to their original names.
-if test -n "$failed"
-then
-	rollback_failure=
-	for file in $rollback
-	do
-		mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
-		rollback_failure="$rollback_failure $file"
-	done
-	if test -n "$rollback_failure"
-	then
-		echo >&2 "WARNING: Some packs in use have been renamed by"
-		echo >&2 "WARNING: prefixing old- to their name, in order to"
-		echo >&2 "WARNING: replace them with the new version of the"
-		echo >&2 "WARNING: file.  But the operation failed, and"
-		echo >&2 "WARNING: attempt to rename them back to their"
-		echo >&2 "WARNING: original names also failed."
-		echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
-		for file in $rollback_failure
-		do
-			echo >&2 "WARNING:   old-$file -> $file"
-		done
-	fi
-	exit 1
-fi
-
-# Now the ones with the same name are out of the way...
-fullbases=
-for name in $names
-do
-	fullbases="$fullbases pack-$name"
-	chmod a-w "$PACKTMP-$name.pack"
-	chmod a-w "$PACKTMP-$name.idx"
-	mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
-	mv -f "$PACKTMP-$name.idx"  "$PACKDIR/pack-$name.idx" ||
-	exit
-done
-
-# Remove the "old-" files
-for name in $names
-do
-	rm -f "$PACKDIR/old-pack-$name.idx"
-	rm -f "$PACKDIR/old-pack-$name.pack"
-done
-
-# End of pack replacement.
-
-if test "$remove_redundant" = t
-then
-	# We know $existing are all redundant.
-	if [ -n "$existing" ]
-	then
-		( cd "$PACKDIR" &&
-		  for e in $existing
-		  do
-			case " $fullbases " in
-			*" $e "*) ;;
-			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
-			esac
-		  done
-		)
-	fi
-	git prune-packed ${GIT_QUIET:+-q}
-fi
-
-case "$no_update_info" in
-t) : ;;
-*) git update-server-info ;;
-esac
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.rc2

^ permalink raw reply related	[relevance 3%]

* [RFC PATCHv2] repack: rewrite the shell script in C.
  @ 2013-08-16  0:12  6% ` Stefan Beller
  2013-08-17 13:34  0%   ` René Scharfe
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2013-08-16  0:12 UTC (permalink / raw)
  To: git, mfick, apelisse, Matthieu.Moy, pclouds, iveqy, gitster; +Cc: Stefan Beller

This is the beginning of the rewrite of the repacking.

 * Removed unneeded system header files
 * corrected remove_pack to really remove any pack files with the given
   sha1
 * fail if pack-objects fails
 * Only test t7701 (2nd) fails now  with this patch.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                                        |   2 +-
 builtin.h                                       |   1 +
 builtin/repack.c                                | 411 ++++++++++++++++++++++++
 git-repack.sh => contrib/examples/git-repack.sh |   0
 git.c                                           |   1 +
 5 files changed, 414 insertions(+), 1 deletion(-)
 create mode 100644 builtin/repack.c
 rename git-repack.sh => contrib/examples/git-repack.sh (100%)

diff --git a/Makefile b/Makefile
index ef442eb..4ec5bbe 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -972,6 +971,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..f72911d
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,411 @@
+/*
+ * The shell version was written by Linus Torvalds (2005) and many others.
+ * This is a translation into C by Stefan Beller (2013)
+ */
+
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+/* enabled by default since 22c79eab (2008-06-25) */
+static int delta_base_offset = 1;
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+static void remove_temporary_files() {
+	DIR *dir;
+	struct dirent *e;
+	char *prefix, *path, *fname;
+
+	prefix = xmalloc(strlen(".tmp-10000-pack") + 1);
+	sprintf(prefix, ".tmp-%d-pack", getpid());
+
+	path = xmalloc(strlen(get_object_directory()) + strlen("/pack") + 1);
+	sprintf(path, "%s/pack", get_object_directory());
+
+	fname = xmalloc(strlen(path) + strlen("/")
+		+ strlen(prefix) + strlen("/")
+		+ 40 + strlen(".pack") + 1);
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!prefixcmp(e->d_name, prefix)) {
+			sprintf(fname, "%s/%s", path, e->d_name);
+			unlink(fname);
+		}
+	}
+	free(fname);
+	free(prefix);
+	free(path);
+	closedir(dir);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+void get_pack_sha1_list(char *packdir, struct string_list *sha1_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *path, *suffix;
+
+	path = xmalloc(strlen(get_object_directory()) + strlen("/pack") + 1);
+	sprintf(path, "%s/pack", get_object_directory());
+
+	suffix = ".pack";
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!suffixcmp(e->d_name, suffix)) {
+			char buf[255], *sha1;
+			strcpy(buf, e->d_name);
+			buf[strlen(e->d_name) - strlen(suffix)] = '\0';
+			sha1 = &buf[strlen(e->d_name) - strlen(suffix) - 40];
+			string_list_append(sha1_list, sha1);
+		}
+	}
+	free(path);
+	closedir(dir);
+}
+
+/*
+ * remove_pack will remove any files following the pattern *${SHA1}.{EXT}
+ * where EXT is one of {pack, idx, keep}. The SHA1 consists of 40 chars and
+ * is specified by the sha1 parameter.
+ * path is specifying the directory in which all found files will be deleted.
+ */
+void remove_pack(char *path, char* sha1)
+{
+	DIR *dir;
+	struct dirent *e;
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+
+		char *sha_begin, *sha_end;
+		sha_end = e->d_name + strlen(e->d_name);
+		while (sha_end > e->d_name && *sha_end != '.')
+			sha_end--;
+
+		/* do not touch files not ending in .pack, .idx or .keep */
+		if (strcmp(sha_end, ".pack") &&
+			strcmp(sha_end, ".idx") &&
+			strcmp(sha_end, ".keep"))
+			continue;
+
+		sha_begin = sha_end - 40;
+
+		if (sha_begin >= e->d_name && !strncmp(sha_begin, sha1, 40)) {
+			char *fname;
+			fname = xmalloc(strlen(path) + 1 + strlen(e->d_name));
+			sprintf(fname, "%s/%s", path, e->d_name);
+			unlink(fname);
+			/*TODO: free(fname); fails here sometimes, needs investigation*/
+		}
+	}
+	closedir(dir);
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix) {
+
+	int pack_everything = 0;
+	int pack_everything_but_loose = 0;
+	int delete_redundant = 0;
+	unsigned long unpack_unreachable = 0;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+	char *packdir, *packtmp;
+	const char *cmd_args[20];
+	int cmd_i = 0;
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	struct stat statbuffer;
+	char window_str[64], window_mem_str[64], depth_str[64], max_pack_size_str[64];
+
+	struct option builtin_repack_options[] = {
+		OPT_BOOL('a', "all", &pack_everything,
+				N_("pack everything in a single pack")),
+		OPT_BOOL('A', "all-but-loose", &pack_everything_but_loose,
+				N_("same as -a, and turn unreachable objects loose")),
+		OPT_BOOL('d', "delete-redundant", &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', "no-reuse-delta", &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', "no-reuse-object", &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_DATE(0, "unpack-unreachable", &unpack_unreachable,
+				N_("with -A, do not loosen objects older than this Packing constraints")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	packdir = mkpath("%s/pack", get_object_directory());
+	packtmp = xmalloc(strlen(packdir) + strlen("/.tmp-10000-pack") + 1);
+	sprintf(packtmp, "%s/.tmp-%d-pack", packdir, getpid());
+
+	remove_temporary_files();
+
+	cmd_args[cmd_i++] = "pack-objects";
+	cmd_args[cmd_i++] = "--keep-true-parents";
+	cmd_args[cmd_i++] = "--honor-pack-keep";
+	cmd_args[cmd_i++] = "--non-empty";
+	cmd_args[cmd_i++] = "--all";
+	cmd_args[cmd_i++] = "--reflog";
+
+	if (window) {
+		sprintf(window_str, "--window=%u", window);
+		cmd_args[cmd_i++] = window_str;
+	}
+	if (window_memory) {
+		sprintf(window_mem_str, "--window-memory=%u", window_memory);
+		cmd_args[cmd_i++] = window_str;
+	}
+	if (depth) {
+		sprintf(depth_str, "--depth=%u", depth);
+		cmd_args[cmd_i++] = depth_str;
+	}
+	if (max_pack_size) {
+		sprintf(max_pack_size_str, "--max_pack_size=%u", max_pack_size);
+		cmd_args[cmd_i++] = max_pack_size_str;
+	}
+
+	if (pack_everything + pack_everything_but_loose == 0) {
+		cmd_args[cmd_i++] = "--unpacked";
+		cmd_args[cmd_i++] = "--incremental";
+	} else {
+		if (pack_everything_but_loose)
+			cmd_args[cmd_i++] = "--unpack-unreachable";
+
+		struct string_list sha1_list = STRING_LIST_INIT_DUP;
+		get_pack_sha1_list(packdir, &sha1_list);
+		for_each_string_list_item(item, &sha1_list) {
+			char *fname;
+			fname = xmalloc(strlen(packdir) + strlen("/") + 40 + strlen(".keep"));
+			sprintf(fname, "%s/%s.keep", packdir, item->string);
+			if (stat(fname, &statbuffer) && S_ISREG(statbuffer.st_mode)) {
+				/* when the keep file is there, we're ignoring that pack */
+			} else {
+				string_list_append(&existing_packs, item->string);
+			}
+		}
+
+		if (existing_packs.nr && unpack_unreachable && delete_redundant) {
+			/*
+			 * TODO: convert unpack_unreachable (being time since epoch)
+			 * to an aproxidate again
+			 */
+			cmd_args[cmd_i++] = "--unpack-unreachable=$DATE";
+		}
+	}
+
+	if (local)
+		cmd_args[cmd_i++] = "--local";
+
+	if (delta_base_offset)
+		cmd_args[cmd_i++] = "--delta-base-offset";
+
+	cmd_args[cmd_i++] = packtmp;
+	cmd_args[cmd_i] = NULL;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = cmd_args;
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	if (run_command(&cmd))
+		return 1;
+
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_DUP;
+
+	char line[1024];
+	int counter = 0;
+	FILE *out = xfdopen(cmd.out, "r");
+	while (fgets(line, sizeof(line), out)) {
+		/* a line consists of 40 hex chars + '\n' */
+		assert(strlen(line) == 41);
+		line[40] = '\0';
+		string_list_append(&names, line);
+		counter++;
+	}
+	if (!counter)
+		printf("Nothing new to pack.\n");
+	fclose(out);
+
+	char *fname, *fname_old;
+	fname = xmalloc(strlen(packdir) + strlen("/old-pack-") + 40 + strlen(".pack") + 1);
+	strcpy(fname, packdir);
+	strcpy(fname + strlen(packdir), "/");
+
+	fname_old = xmalloc(strlen(packdir) + strlen("/old-pack-") + 40 + strlen(".pack") + 1);
+	strcpy(fname_old, packdir);
+	strcpy(fname_old + strlen(packdir), "/");
+	char *exts[2] = {".idx", ".pack"};
+
+	int failed = 0;
+
+	for_each_string_list_item(item, &names) {
+		int ext;
+		for (ext = 0; ext < 1; ext++) {
+			strcpy(fname + strlen(packdir) + 1, item->string);
+			strcpy(fname + strlen(packdir) + 41, exts[ext]);
+			if (!file_exists(fname))
+				continue;
+
+			strcpy(fname_old, packdir);
+			strcpy(fname_old + strlen(packdir), "/old-");
+			strcpy(fname_old + strlen(packdir) + 5, item->string);
+			strcpy(fname_old + strlen(packdir) + 45, exts[ext]);
+			if (file_exists(fname_old))
+				unlink(fname_old);
+
+			if (rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			string_list_append(&rollback, fname);
+		}
+		if (failed)
+			/* set to last element to break while loop */
+			item = names.items + names.nr;
+	}
+	if (failed) {
+		struct string_list rollback_failure;
+
+		for_each_string_list_item(item, &rollback) {
+			sprintf(fname, "%s/%s", packdir, item->string);
+			sprintf(fname_old, "%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+		}
+
+		if (rollback.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in $PACKDIR manually:\n");
+			for (i = 0; i < rollback.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback.items[i].string,
+					rollback.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	struct string_list fullbases = STRING_LIST_INIT_DUP;
+	for_each_string_list_item(item, &names) {
+		string_list_append(&fullbases, item->string);
+
+		sprintf(fname, "%s/pack-%s.pack", packdir, item->string);
+		sprintf(fname_old, "%s-%s.pack", packtmp, item->string);
+		stat(fname_old, &statbuffer);
+		statbuffer.st_mode &= ~S_IWOTH;
+		chmod(fname_old, statbuffer.st_mode);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+
+		sprintf(fname, "%s/pack-%s.idx", packdir, item->string);
+		sprintf(fname_old, "%s-%s.idx", packtmp, item->string);
+		stat(fname_old, &statbuffer);
+		statbuffer.st_mode &= ~S_IWOTH;
+		chmod(fname_old, statbuffer.st_mode);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		sprintf(fname, "%s/old-pack-%s.idx", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+
+		sprintf(fname, "%s/old-pack-%s.pack", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+	}
+
+	/* End of pack replacement. */
+	if (delete_redundant) {
+		sort_string_list(&fullbases);
+		fname = xmalloc(strlen(packtmp) + strlen("/") + 40 + strlen(".pack") + 1);
+		for_each_string_list_item(item, &existing_packs) {
+			if (!string_list_has_string(&fullbases, item->string))
+				remove_pack(packdir, item->string);
+		}
+		free(fname);
+		cmd_i = 0;
+		cmd_args[cmd_i++] = "prune-packed";
+		cmd_args[cmd_i++] = NULL;
+		/* TODO: pass argument: ${GIT_QUIET:+-q} */
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+
+	if (!no_update_server_info) {
+		cmd_i = 0;
+		cmd_args[cmd_i++] = "update-server-info";
+		cmd_args[cmd_i++] = NULL;
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+	return 0;
+}
+
diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
similarity index 100%
rename from git-repack.sh
rename to contrib/examples/git-repack.sh
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.rc3.1.gc1ebd90

^ permalink raw reply related	[relevance 6%]

* Re: [RFC PATCHv2] repack: rewrite the shell script in C.
  2013-08-16  0:12  6% ` [RFC PATCHv2] " Stefan Beller
@ 2013-08-17 13:34  0%   ` René Scharfe
  0 siblings, 0 replies; 200+ results
From: René Scharfe @ 2013-08-17 13:34 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, mfick, apelisse, Matthieu.Moy, pclouds, iveqy, gitster

>
>
> This is the beginning of the rewrite of the repacking.
>
>  * Removed unneeded system header files
>  * corrected remove_pack to really remove any pack files with the given
>    sha1
>  * fail if pack-objects fails
>  * Only test t7701 (2nd) fails now  with this patch.
>
> Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
> ---
>  Makefile                                        |   2 +-
>  builtin.h                                       |   1 +
>  builtin/repack.c                                | 411 ++++++++++++++++++++++++
>  git-repack.sh => contrib/examples/git-repack.sh |   0
>  git.c                                           |   1 +
>  5 files changed, 414 insertions(+), 1 deletion(-)
>  create mode 100644 builtin/repack.c
>  rename git-repack.sh => contrib/examples/git-repack.sh (100%)
>
> diff --git a/Makefile b/Makefile
> index ef442eb..4ec5bbe 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
>  SCRIPT_SH += git-quiltimport.sh
>  SCRIPT_SH += git-rebase.sh
>  SCRIPT_SH += git-remote-testgit.sh
> -SCRIPT_SH += git-repack.sh
>  SCRIPT_SH += git-request-pull.sh
>  SCRIPT_SH += git-stash.sh
>  SCRIPT_SH += git-submodule.sh
> @@ -972,6 +971,7 @@ BUILTIN_OBJS += builtin/reflog.o
>  BUILTIN_OBJS += builtin/remote.o
>  BUILTIN_OBJS += builtin/remote-ext.o
>  BUILTIN_OBJS += builtin/remote-fd.o
> +BUILTIN_OBJS += builtin/repack.o
>  BUILTIN_OBJS += builtin/replace.o
>  BUILTIN_OBJS += builtin/rerere.o
>  BUILTIN_OBJS += builtin/reset.o
> diff --git a/builtin.h b/builtin.h
> index 8afa2de..b56cf07 100644
> --- a/builtin.h
> +++ b/builtin.h
> @@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
>  extern int cmd_remote(int argc, const char **argv, const char *prefix);
>  extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
>  extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
> +extern int cmd_repack(int argc, const char **argv, const char *prefix);
>  extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
>  extern int cmd_rerere(int argc, const char **argv, const char *prefix);
>  extern int cmd_reset(int argc, const char **argv, const char *prefix);
> diff --git a/builtin/repack.c b/builtin/repack.c
> new file mode 100644
> index 0000000..f72911d
> --- /dev/null
> +++ b/builtin/repack.c
> @@ -0,0 +1,411 @@
> +/*
> + * The shell version was written by Linus Torvalds (2005) and many others.
> + * This is a translation into C by Stefan Beller (2013)
> + */
> +
> +#include "builtin.h"
> +#include "cache.h"
> +#include "dir.h"
> +#include "parse-options.h"
> +#include "run-command.h"
> +#include "sigchain.h"
> +#include "strbuf.h"
> +#include "string-list.h"
> +
> +static const char *const git_repack_usage[] = {
> +	N_("git repack [options]"),
> +	NULL
> +};
> +
> +/* enabled by default since 22c79eab (2008-06-25) */
> +static int delta_base_offset = 1;
> +
> +static int repack_config(const char *var, const char *value, void *cb)
> +{
> +	if (!strcmp(var, "repack.usedeltabaseoffset")) {
> +		delta_base_offset = git_config_bool(var, value);
> +		return 0;
> +	}
> +	return git_default_config(var, value, cb);
> +}
> +
> +static void remove_temporary_files() {
> +	DIR *dir;
> +	struct dirent *e;
> +	char *prefix, *path, *fname;
> +
> +	prefix = xmalloc(strlen(".tmp-10000-pack") + 1);
> +	sprintf(prefix, ".tmp-%d-pack", getpid());

This will overflow for PIDs with more than five digits. Better use a 
strbuf and build the string with strbuf_addf.  Or better, use mkpathdup, 
which does that under the hood.

> +
> +	path = xmalloc(strlen(get_object_directory()) + strlen("/pack") + 1);
> +	sprintf(path, "%s/pack", get_object_directory());

mkpathdup?

> +
> +	fname = xmalloc(strlen(path) + strlen("/")
> +		+ strlen(prefix) + strlen("/")
> +		+ 40 + strlen(".pack") + 1);
> +
> +	dir = opendir(path);
> +	while ((e = readdir(dir)) != NULL) {
> +		if (!prefixcmp(e->d_name, prefix)) {
> +			sprintf(fname, "%s/%s", path, e->d_name);

If someone has a directory entry that begins with 'prefix' but is longer 
than expected this will overflow.  That's unlikely, but lets avoid it 
outright.  You could use a strbuf instead and reset it to the length of 
the prefix at the start of the loop (with strbuf_setlen), before adding 
the entry's name.

> +			unlink(fname);
> +		}
> +	}
> +	free(fname);
> +	free(prefix);
> +	free(path);
> +	closedir(dir);
> +}
> +
> +static void remove_pack_on_signal(int signo)
> +{
> +	remove_temporary_files();
> +	sigchain_pop(signo);
> +	raise(signo);
> +}
> +
> +void get_pack_sha1_list(char *packdir, struct string_list *sha1_list)
> +{
> +	DIR *dir;
> +	struct dirent *e;
> +	char *path, *suffix;
> +
> +	path = xmalloc(strlen(get_object_directory()) + strlen("/pack") + 1);
> +	sprintf(path, "%s/pack", get_object_directory());

mkpathdup again.

Or would it make sense to cd into the pack directory and avoid these 
string manipulations outright?  Probably not if we need to call other 
git functions later on.

> +
> +	suffix = ".pack";
> +
> +	dir = opendir(path);
> +	while ((e = readdir(dir)) != NULL) {
> +		if (!suffixcmp(e->d_name, suffix)) {
> +			char buf[255], *sha1;
> +			strcpy(buf, e->d_name);
> +			buf[strlen(e->d_name) - strlen(suffix)] = '\0';
> +			sha1 = &buf[strlen(e->d_name) - strlen(suffix) - 40];
> +			string_list_append(sha1_list, sha1);

You could avoid the need for a temporary buffer by using xmemdupz and 
string_list_append_nodup instead.

> +		}
> +	}
> +	free(path);
> +	closedir(dir);
> +}
> +
> +/*
> + * remove_pack will remove any files following the pattern *${SHA1}.{EXT}
> + * where EXT is one of {pack, idx, keep}. The SHA1 consists of 40 chars and
> + * is specified by the sha1 parameter.
> + * path is specifying the directory in which all found files will be deleted.
> + */
> +void remove_pack(char *path, char* sha1)
> +{
> +	DIR *dir;
> +	struct dirent *e;
> +
> +	dir = opendir(path);
> +	while ((e = readdir(dir)) != NULL) {
> +

Extra newline.

> +		char *sha_begin, *sha_end;
> +		sha_end = e->d_name + strlen(e->d_name);
> +		while (sha_end > e->d_name && *sha_end != '.')
> +			sha_end--;
> +
> +		/* do not touch files not ending in .pack, .idx or .keep */
> +		if (strcmp(sha_end, ".pack") &&
> +			strcmp(sha_end, ".idx") &&
> +			strcmp(sha_end, ".keep"))
> +			continue;
> +
> +		sha_begin = sha_end - 40;
> +
> +		if (sha_begin >= e->d_name && !strncmp(sha_begin, sha1, 40)) {
> +			char *fname;
> +			fname = xmalloc(strlen(path) + 1 + strlen(e->d_name));
> +			sprintf(fname, "%s/%s", path, e->d_name);

mkpathdup..

> +			unlink(fname);
> +			/*TODO: free(fname); fails here sometimes, needs investigation*/

Strange.  Perhaps valgrind can tell you what's wrong.

> +		}
> +	}
> +	closedir(dir);
> +}

Hmm, stepping back a bit, why not just build the paths and call unlink 
for them right away, without readdir?  The shell version only ever 
deletes existing .pack files (those in $existing alias existing_packs) 
as well as their .idx and .keep files, if present.  It doesn't use a 
glob pattern, unlike remove_pack here.

> +
> +int cmd_repack(int argc, const char **argv, const char *prefix) {
> +
> +	int pack_everything = 0;
> +	int pack_everything_but_loose = 0;
> +	int delete_redundant = 0;
> +	unsigned long unpack_unreachable = 0;
> +	int window = 0, window_memory = 0;
> +	int depth = 0;
> +	int max_pack_size = 0;
> +	int no_reuse_delta = 0, no_reuse_object = 0;
> +	int no_update_server_info = 0;
> +	int quiet = 0;
> +	int local = 0;
> +	char *packdir, *packtmp;
> +	const char *cmd_args[20];
> +	int cmd_i = 0;
> +	struct child_process cmd;
> +	struct string_list_item *item;
> +	struct string_list existing_packs = STRING_LIST_INIT_DUP;
> +	struct stat statbuffer;
> +	char window_str[64], window_mem_str[64], depth_str[64], max_pack_size_str[64];
> +
> +	struct option builtin_repack_options[] = {
> +		OPT_BOOL('a', "all", &pack_everything,
> +				N_("pack everything in a single pack")),
> +		OPT_BOOL('A', "all-but-loose", &pack_everything_but_loose,
> +				N_("same as -a, and turn unreachable objects loose")),
> +		OPT_BOOL('d', "delete-redundant", &delete_redundant,
> +				N_("remove redundant packs, and run git-prune-packed")),
> +		OPT_BOOL('f', "no-reuse-delta", &no_reuse_delta,
> +				N_("pass --no-reuse-delta to git-pack-objects")),
> +		OPT_BOOL('F', "no-reuse-object", &no_reuse_object,
> +				N_("pass --no-reuse-object to git-pack-objects")),
> +		OPT_BOOL('n', NULL, &no_update_server_info,
> +				N_("do not run git-update-server-info")),
> +		OPT__QUIET(&quiet, N_("be quiet")),
> +		OPT_BOOL('l', "local", &local,
> +				N_("pass --local to git-pack-objects")),
> +		OPT_DATE(0, "unpack-unreachable", &unpack_unreachable,
> +				N_("with -A, do not loosen objects older than this Packing constraints")),
> +		OPT_INTEGER(0, "window", &window,
> +				N_("size of the window used for delta compression")),
> +		OPT_INTEGER(0, "window-memory", &window_memory,
> +				N_("same as the above, but limit memory size instead of entries count")),
> +		OPT_INTEGER(0, "depth", &depth,
> +				N_("limits the maximum delta depth")),
> +		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
> +				N_("maximum size of each packfile")),
> +		OPT_END()
> +	};
> +
> +	git_config(repack_config, NULL);
> +
> +	argc = parse_options(argc, argv, prefix, builtin_repack_options,
> +				git_repack_usage, 0);
> +
> +	sigchain_push_common(remove_pack_on_signal);
> +
> +	packdir = mkpath("%s/pack", get_object_directory());

Ah, mkpath is already used.  That function is a bit tricky because you 
can only use it with four paths concurrently and some internal functions 
might already need one (or more) of the slots for itself.  It's better 
to consume its output on the spot (like in printf("my path is %s\n", 
mkpath(...));) or use mkpathdup.

> +	packtmp = xmalloc(strlen(packdir) + strlen("/.tmp-10000-pack") + 1);
> +	sprintf(packtmp, "%s/.tmp-%d-pack", packdir, getpid());

mkpathdup again..

> +
> +	remove_temporary_files();
> +
> +	cmd_args[cmd_i++] = "pack-objects";
> +	cmd_args[cmd_i++] = "--keep-true-parents";
> +	cmd_args[cmd_i++] = "--honor-pack-keep";
> +	cmd_args[cmd_i++] = "--non-empty";
> +	cmd_args[cmd_i++] = "--all";
> +	cmd_args[cmd_i++] = "--reflog";
> +
> +	if (window) {
> +		sprintf(window_str, "--window=%u", window);
> +		cmd_args[cmd_i++] = window_str;
> +	}
> +	if (window_memory) {
> +		sprintf(window_mem_str, "--window-memory=%u", window_memory);
> +		cmd_args[cmd_i++] = window_str;
> +	}
> +	if (depth) {
> +		sprintf(depth_str, "--depth=%u", depth);
> +		cmd_args[cmd_i++] = depth_str;
> +	}
> +	if (max_pack_size) {
> +		sprintf(max_pack_size_str, "--max_pack_size=%u", max_pack_size);
> +		cmd_args[cmd_i++] = max_pack_size_str;
> +	}


You can simplify that part by using argv_array and argv_array_pushf.

> +
> +	if (pack_everything + pack_everything_but_loose == 0) {
> +		cmd_args[cmd_i++] = "--unpacked";
> +		cmd_args[cmd_i++] = "--incremental";
> +	} else {
> +		if (pack_everything_but_loose)
> +			cmd_args[cmd_i++] = "--unpack-unreachable";
> +
> +		struct string_list sha1_list = STRING_LIST_INIT_DUP;
> +		get_pack_sha1_list(packdir, &sha1_list);
> +		for_each_string_list_item(item, &sha1_list) {
> +			char *fname;
> +			fname = xmalloc(strlen(packdir) + strlen("/") + 40 + strlen(".keep"));
> +			sprintf(fname, "%s/%s.keep", packdir, item->string);

mkpathdup..

Or maybe go through the entries in the pack directory once, like already 
done in get_pack_sha1_list, and instead of just making a list of .pack 
files, make a list of .keep files as well.  Then work with those lists 
instead of accessing the directory again with stat.

> +			if (stat(fname, &statbuffer) && S_ISREG(statbuffer.st_mode)) {
> +				/* when the keep file is there, we're ignoring that pack */
> +			} else {
> +				string_list_append(&existing_packs, item->string);
> +			}
> +		}
> +
> +		if (existing_packs.nr && unpack_unreachable && delete_redundant) {
> +			/*
> +			 * TODO: convert unpack_unreachable (being time since epoch)
> +			 * to an aproxidate again
> +			 */
> +			cmd_args[cmd_i++] = "--unpack-unreachable=$DATE";
> +		}
> +	}
> +
> +	if (local)
> +		cmd_args[cmd_i++] = "--local";
> +
> +	if (delta_base_offset)
> +		cmd_args[cmd_i++] = "--delta-base-offset";
> +
> +	cmd_args[cmd_i++] = packtmp;
> +	cmd_args[cmd_i] = NULL;
> +
> +	memset(&cmd, 0, sizeof(cmd));
> +	cmd.argv = cmd_args;
> +	cmd.git_cmd = 1;
> +	cmd.out = -1;
> +	cmd.no_stdin = 1;
> +
> +	if (run_command(&cmd))
> +		return 1;
> +
> +	struct string_list names = STRING_LIST_INIT_DUP;
> +	struct string_list rollback = STRING_LIST_INIT_DUP;
> +
> +	char line[1024];
> +	int counter = 0;
> +	FILE *out = xfdopen(cmd.out, "r");
> +	while (fgets(line, sizeof(line), out)) {
> +		/* a line consists of 40 hex chars + '\n' */
> +		assert(strlen(line) == 41);
> +		line[40] = '\0';
> +		string_list_append(&names, line);
> +		counter++;
> +	}
> +	if (!counter)
> +		printf("Nothing new to pack.\n");
> +	fclose(out);
> +
> +	char *fname, *fname_old;
> +	fname = xmalloc(strlen(packdir) + strlen("/old-pack-") + 40 + strlen(".pack") + 1);
> +	strcpy(fname, packdir);
> +	strcpy(fname + strlen(packdir), "/");
> +
> +	fname_old = xmalloc(strlen(packdir) + strlen("/old-pack-") + 40 + strlen(".pack") + 1);
> +	strcpy(fname_old, packdir);
> +	strcpy(fname_old + strlen(packdir), "/");
> +	char *exts[2] = {".idx", ".pack"};
> +
> +	int failed = 0;
> +
> +	for_each_string_list_item(item, &names) {
> +		int ext;
> +		for (ext = 0; ext < 1; ext++) {
> +			strcpy(fname + strlen(packdir) + 1, item->string);
> +			strcpy(fname + strlen(packdir) + 41, exts[ext]);
> +			if (!file_exists(fname))
> +				continue;
> +
> +			strcpy(fname_old, packdir);
> +			strcpy(fname_old + strlen(packdir), "/old-");
> +			strcpy(fname_old + strlen(packdir) + 5, item->string);
> +			strcpy(fname_old + strlen(packdir) + 45, exts[ext]);
> +			if (file_exists(fname_old))
> +				unlink(fname_old);
> +
> +			if (rename(fname, fname_old)) {
> +				failed = 1;
> +				break;
> +			}
> +			string_list_append(&rollback, fname);

mkpathdup with string_list_append_nodup instead?

> +		}
> +		if (failed)
> +			/* set to last element to break while loop */
> +			item = names.items + names.nr;
> +	}
> +	if (failed) {
> +		struct string_list rollback_failure;
> +
> +		for_each_string_list_item(item, &rollback) {
> +			sprintf(fname, "%s/%s", packdir, item->string);
> +			sprintf(fname_old, "%s/old-%s", packdir, item->string);
> +			if (rename(fname_old, fname))
> +				string_list_append(&rollback_failure, fname);

Dito.

> +		}
> +
> +		if (rollback.nr) {
> +			int i;
> +			fprintf(stderr,
> +				"WARNING: Some packs in use have been renamed by\n"
> +				"WARNING: prefixing old- to their name, in order to\n"
> +				"WARNING: replace them with the new version of the\n"
> +				"WARNING: file.  But the operation failed, and\n"
> +				"WARNING: attempt to rename them back to their\n"
> +				"WARNING: original names also failed.\n"
> +				"WARNING: Please rename them in $PACKDIR manually:\n");
> +			for (i = 0; i < rollback.nr; i++)
> +				fprintf(stderr, "WARNING:   old-%s -> %s\n",
> +					rollback.items[i].string,
> +					rollback.items[i].string);
> +		}
> +		exit(1);
> +	}
> +
> +	/* Now the ones with the same name are out of the way... */
> +	struct string_list fullbases = STRING_LIST_INIT_DUP;
> +	for_each_string_list_item(item, &names) {
> +		string_list_append(&fullbases, item->string);

Why make a copy of 'names'?  Can't you use it directly instead of 
'fullbases'?  Ah, the Shell version adds a "pack-" at the beginning of 
each string.  We don't need to do that and thus can get rid of that 
extra list, no?

> +
> +		sprintf(fname, "%s/pack-%s.pack", packdir, item->string);
> +		sprintf(fname_old, "%s-%s.pack", packtmp, item->string);
> +		stat(fname_old, &statbuffer);
> +		statbuffer.st_mode &= ~S_IWOTH;
> +		chmod(fname_old, statbuffer.st_mode);
> +		if (rename(fname_old, fname))
> +			die("Could not rename packfile: %s -> %s", fname_old, fname);
> +
> +		sprintf(fname, "%s/pack-%s.idx", packdir, item->string);
> +		sprintf(fname_old, "%s-%s.idx", packtmp, item->string);
> +		stat(fname_old, &statbuffer);
> +		statbuffer.st_mode &= ~S_IWOTH;
> +		chmod(fname_old, statbuffer.st_mode);
> +		if (rename(fname_old, fname))
> +			die("Could not rename packfile: %s -> %s", fname_old, fname);
> +	}
> +
> +	/* Remove the "old-" files */
> +	for_each_string_list_item(item, &names) {
> +		sprintf(fname, "%s/old-pack-%s.idx", packdir, item->string);
> +		if (remove_path(fname))
> +			die("Could not remove file: %s", fname);
> +
> +		sprintf(fname, "%s/old-pack-%s.pack", packdir, item->string);
> +		if (remove_path(fname))
> +			die("Could not remove file: %s", fname);
> +	}
> +
> +	/* End of pack replacement. */
> +	if (delete_redundant) {
> +		sort_string_list(&fullbases);
> +		fname = xmalloc(strlen(packtmp) + strlen("/") + 40 + strlen(".pack") + 1);
> +		for_each_string_list_item(item, &existing_packs) {
> +			if (!string_list_has_string(&fullbases, item->string))
> +				remove_pack(packdir, item->string);
> +		}
> +		free(fname);

Why allocate memory for fname and give it back unused?

> +		cmd_i = 0;
> +		cmd_args[cmd_i++] = "prune-packed";
> +		cmd_args[cmd_i++] = NULL;
> +		/* TODO: pass argument: ${GIT_QUIET:+-q} */
> +		memset(&cmd, 0, sizeof(cmd));
> +		cmd.argv = cmd_args;
> +		cmd.git_cmd = 1;
> +		run_command(&cmd);
> +	}
> +
> +	if (!no_update_server_info) {
> +		cmd_i = 0;
> +		cmd_args[cmd_i++] = "update-server-info";
> +		cmd_args[cmd_i++] = NULL;
> +
> +		memset(&cmd, 0, sizeof(cmd));
> +		cmd.argv = cmd_args;
> +		cmd.git_cmd = 1;
> +		run_command(&cmd);
> +	}
> +	return 0;
> +}
> +
> diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
> similarity index 100%
> rename from git-repack.sh
> rename to contrib/examples/git-repack.sh
> diff --git a/git.c b/git.c
> index 2025f77..03510be 100644
> --- a/git.c
> +++ b/git.c
> @@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
>  		{ "remote", cmd_remote, RUN_SETUP },
>  		{ "remote-ext", cmd_remote_ext },
>  		{ "remote-fd", cmd_remote_fd },
> +		{ "repack", cmd_repack, RUN_SETUP },
>  		{ "replace", cmd_replace, RUN_SETUP },
>  		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
>  		{ "rerere", cmd_rerere, RUN_SETUP },
> -- 1.8.4.rc3.1.gc1ebd90
>

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] tag: Use OPT_BOOL instead of OPT_BOOLEAN to allow one action multiple times
  2013-07-31 23:10  5%         ` Junio C Hamano
@ 2013-08-17 15:01  4%           ` Stefano Lattarini
  0 siblings, 0 replies; 200+ results
From: Stefano Lattarini @ 2013-08-17 15:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Stefan Beller, git

(Going through old mail today, sorry for the late reply)

On 08/01/2013 12:10 AM, Junio C Hamano wrote:> Stefan Beller 
<stefanbeller@googlemail.com> writes:
 >
 >> On 07/31/13 00:28, Junio C Hamano wrote:
 >>>
 >>> we could just do
 >>>
 >>> #define OPT_CMDMODE(s, l, v, h) \
 >>>      { OPTION_CMDMODE, (s), (l), (v), NULL, \
 >>>        (h), PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, (s) }
 >>>
 >>
 >> I agree that's a better proposal than mine.
 >
 > By the way, I haven't convinced myself that it is a good idea in
 > general to encourage more use of command mode options, so I am a bit
 > reluctant to add this before knowing which direction in the longer
 > term we are going.
 >
 >   - Some large-ish Git subcommands, like "git submodule", use the
 >     mode word (e.g. "git submodule status") to specify the operation
 >     mode (youe could consider "status" a subsubcommand that
 >     "submodule" subcommand takes).  These commands typically began
 >     their life from day one with the mode words.
 >
 >   - On the other hand, many Git subcommands, like "git tag", have
 >     "the primary operation mode" (e.g. "create a new one" is the
 >     primary operation mode for "git tag"), and use command mode
 >     options to specify other operation modes (e.g. "--delete").
 >     These commands started as single purpose commands (i.e. to
 >     perform their "primary operation") but have organically grown
 >     over time and acquired command mode options to invoke their
 >     secondary operations.
 >
 > As an end user, you need to learn which style each command takes,
 > which is an unnecessary burden at the UI level.  In the longer term,
 > we may want to consider picking a single style, and migrating
 > everybody to it.  If I have to vote today, I would say we should
 > teach "git submodule" to also take command mode options (e.g. "git
 > submodule --status" will be understood the same way as "git
 > submodule status"), make them issue warnings when mode words are
 > used and encourage users to use command mode options instead, and
 > optionally remove the support of mode words at a large version bump
 > like 3.0.
 >
 > One clear advantage mode words have over command mode options is
 > that there is no room for end user confusion.  The first word after
 > "git subcmd" is the mode word, and you will not even dream of asking
 > "what would 'git submodule add del foo' do?" as it is nonsensical.
 > The command mode options, on the other hand, gives too much useless
 > flexibility to ask for nonsense, e.g. "git tag --delete --verify",
 > "git tag --no-delete --delete", etc., and extra code needs to detect
 > and reject combinations.  But commands that took mode options cannot
 > be easily migrated to take mode words without hurting existing users
 > and scripts (e.g. "git tag delete master" can never be a request to
 > delete the tag 'master', as it is a request to create a tag whose
 > name is 'delete' that points at the same object as 'master' points
 > at).
 >
Why not encourage the use of a standardized '--action' option instead?
This can work with lesser compatibility headaches for both the commands
taking mode options and the commands taking mode words:

   "git submodule init"   becomes  "git submodule --action=init"
   "git tag --delete TAG" becomes  "git tag --action=delete TAGNAME"

Commands that have a "primary operation mode" can keep the use
of --action optional, while commands that have no such sensible
primary mode can make it mandatory (again, this gives more compatibility 
with the existing syntax).  And the old syntax
can be supported in parallel to the new one for a potentially
indefinite time; albeit, if I were to propose a timetable, I'd
got for:

   - Git 2.0: the new syntax is introduced
   - Git 2.x: any use the old syntax starts to trigger warnings
     (which can be silenced with a config option)
   - Git 3.0: any use the old syntax starts to trigger fatal
     errors (which can be turned into mandatory warnings with
     a config option)
   - Git 4.0: any use the old syntax starts to trigger
     mandatory fatal errors.
   - Git 4.x: Remove any handling of the old syntax.

Just my 2 cents,
   Stefano

^ permalink raw reply	[relevance 4%]

* [RFC PATCHv3] repack: rewrite the shell script in C.
  @ 2013-08-18 14:36  6% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-08-18 14:36 UTC (permalink / raw)
  To: git, l.s.r, mfick, apelisse, Matthieu.Moy, pclouds, iveqy,
	gitster
  Cc: Stefan Beller

This is the beginning of the rewrite of the repacking.

 * replace all plain string handling functions
   by git helper functions, most often mkpathdup
 * use argv-array structs to pass arguments to
   other git invocations.

Only test t7701 (2nd) fails now  with this patch.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                                        |   2 +-
 builtin.h                                       |   1 +
 builtin/repack.c                                | 385 ++++++++++++++++++++++++
 git-repack.sh => contrib/examples/git-repack.sh |   0
 git.c                                           |   1 +
 5 files changed, 388 insertions(+), 1 deletion(-)
 create mode 100644 builtin/repack.c
 rename git-repack.sh => contrib/examples/git-repack.sh (100%)

diff --git a/Makefile b/Makefile
index ef442eb..4ec5bbe 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -972,6 +971,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..190eb5f
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,385 @@
+/*
+ * The shell version was written by Linus Torvalds (2005) and many others.
+ * This is a translation into C by Stefan Beller (2013)
+ */
+
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+
+#include "argv-array.h"
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+/* enabled by default since 22c79eab (2008-06-25) */
+static int delta_base_offset = 1;
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+static void remove_temporary_files() {
+	DIR *dir;
+	struct dirent *e;
+	char *prefix, *path;
+
+	prefix = mkpathdup(".tmp-%d-pack", getpid());
+	path = mkpathdup("%s/pack", get_object_directory());
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!prefixcmp(e->d_name, prefix)) {
+			struct strbuf fname = STRBUF_INIT;
+			strbuf_addf(&fname, "%s/%s", path, e->d_name);
+			unlink(strbuf_detach(&fname, NULL));
+		}
+	}
+	free(prefix);
+	free(path);
+	closedir(dir);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+void get_pack_sha1_list(char *packdir, struct string_list *sha1_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *path, *suffix;
+
+	path = mkpathdup("%s/pack", get_object_directory());
+	suffix = ".pack";
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!suffixcmp(e->d_name, suffix)) {
+			char *buf, *sha1;
+			buf = xmemdupz(e->d_name, strlen(e->d_name));
+			buf[strlen(e->d_name) - strlen(suffix)] = '\0';
+			if (strlen(e->d_name) - strlen(suffix) > 40) {
+				sha1 = &buf[strlen(e->d_name) - strlen(suffix) - 40];
+				string_list_append_nodup(sha1_list, sha1);
+			} else {
+				/*TODO: what should happen to pack files having no 40 char sha1 specifier?*/
+			}
+		}
+	}
+	free(path);
+	closedir(dir);
+}
+
+/*
+ * remove_pack will remove any files following the pattern *${SHA1}.{EXT}
+ * where EXT is one of {pack, idx, keep}. The SHA1 consists of 40 chars and
+ * is specified by the sha1 parameter.
+ * path is specifying the directory in which all found files will be deleted.
+ */
+void remove_pack(char *path, char* sha1)
+{
+	DIR *dir;
+	struct dirent *e;
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		char *sha_begin, *sha_end;
+		sha_end = e->d_name + strlen(e->d_name);
+		while (sha_end > e->d_name && *sha_end != '.')
+			sha_end--;
+
+		/* do not touch files not ending in .pack, .idx or .keep */
+		if (strcmp(sha_end, ".pack") &&
+			strcmp(sha_end, ".idx") &&
+			strcmp(sha_end, ".keep"))
+			continue;
+
+		sha_begin = sha_end - 40;
+
+		if (sha_begin >= e->d_name && !strncmp(sha_begin, sha1, 40)) {
+			char *fname;
+			fname = mkpathdup("%s/%s", path, e->d_name);
+			unlink(fname);
+			free(fname);
+		}
+	}
+	closedir(dir);
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix) {
+
+	int pack_everything = 0;
+	int pack_everything_but_loose = 0;
+	int delete_redundant = 0;
+	char *unpack_unreachable = NULL;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+	char *packdir, *packtmp;
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	struct stat statbuffer;
+
+	struct option builtin_repack_options[] = {
+		OPT_BOOL('a', "all", &pack_everything,
+				N_("pack everything in a single pack")),
+		OPT_BOOL('A', "all-but-loose", &pack_everything_but_loose,
+				N_("same as -a, and turn unreachable objects loose")),
+		OPT_BOOL('d', "delete-redundant", &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', "no-reuse-delta", &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', "no-reuse-object", &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
+				N_("with -A, do not loosen objects older than this Packing constraints")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	packdir = mkpathdup("%s/pack", get_object_directory());
+	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, getpid());
+
+	remove_temporary_files();
+
+	struct argv_array cmd_args = ARGV_ARRAY_INIT;
+	argv_array_push(&cmd_args, "pack-objects");
+	argv_array_push(&cmd_args, "--keep-true-parents");
+	argv_array_push(&cmd_args, "--honor-pack-keep");
+	argv_array_push(&cmd_args, "--non-empty");
+	argv_array_push(&cmd_args, "--all");
+	argv_array_push(&cmd_args, "--reflog");
+
+	if (window)
+		argv_array_pushf(&cmd_args, "--window=%u", window);
+
+	if (window_memory)
+		argv_array_pushf(&cmd_args, "--window-memory=%u", window_memory);
+
+	if (depth)
+		argv_array_pushf(&cmd_args, "--depth=%u", depth);
+
+	if (max_pack_size)
+		argv_array_pushf(&cmd_args, "--max_pack_size=%u", max_pack_size);
+
+	if (pack_everything + pack_everything_but_loose == 0) {
+		argv_array_push(&cmd_args, "--unpacked");
+		argv_array_push(&cmd_args, "--incremental");
+	} else {
+		if (pack_everything_but_loose)
+			argv_array_push(&cmd_args, "--unpack-unreachable");
+
+		struct string_list sha1_list = STRING_LIST_INIT_DUP;
+		get_pack_sha1_list(packdir, &sha1_list);
+		for_each_string_list_item(item, &sha1_list) {
+			char *fname;
+			fname = mkpathdup("%s/%s.keep", packdir, item->string);
+			if (stat(fname, &statbuffer) && S_ISREG(statbuffer.st_mode)) {
+				/* when the keep file is there, we're ignoring that pack */
+			} else {
+				string_list_append(&existing_packs, item->string);
+			}
+			free(fname);
+		}
+
+		if (existing_packs.nr && unpack_unreachable && delete_redundant) {
+			argv_array_pushf(&cmd_args, "--unpack-unreachable=%s", unpack_unreachable);
+		}
+	}
+
+	if (local)
+		argv_array_push(&cmd_args,  "--local");
+
+	if (delta_base_offset)
+		argv_array_push(&cmd_args,  "--delta-base-offset");
+
+	argv_array_push(&cmd_args, packtmp);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = argv_array_detach(&cmd_args, NULL);
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	if (run_command(&cmd))
+		return 1;
+
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_DUP;
+
+	char line[1024];
+	int counter = 0;
+	FILE *out = xfdopen(cmd.out, "r");
+	while (fgets(line, sizeof(line), out)) {
+		/* a line consists of 40 hex chars + '\n' */
+		assert(strlen(line) == 41);
+		line[40] = '\0';
+		string_list_append(&names, line);
+		counter++;
+	}
+	if (!counter)
+		printf("Nothing new to pack.\n");
+	fclose(out);
+
+	char *exts[2] = {".idx", ".pack"};
+	int failed = 0;
+	for_each_string_list_item(item, &names) {
+		int ext;
+		for (ext = 0; ext < 1; ext++) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s%s", packdir, item->string, exts[ext]);
+			if (!file_exists(fname)) {
+				free(fname);
+				continue;
+			}
+
+			fname_old = mkpathdup("%s/old-%s%s", packdir, item->string, exts[ext]);
+			if (file_exists(fname_old))
+				unlink(fname_old);
+
+			if (rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			string_list_append_nodup(&rollback, fname);
+		}
+		if (failed)
+			/* set to last element to break for_each loop */
+			item = names.items + names.nr;
+	}
+	if (failed) {
+		struct string_list rollback_failure;
+		for_each_string_list_item(item, &rollback) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s", packdir, item->string);
+			fname_old = mkpathdup("%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+			free(fname);
+			free(fname_old);
+		}
+
+		if (rollback.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in $PACKDIR manually:\n");
+			for (i = 0; i < rollback.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback.items[i].string,
+					rollback.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	for_each_string_list_item(item, &names) {
+		char *fname, *fname_old;
+		fname = mkpathdup("%s/pack-%s.pack", packdir, item->string);
+		fname_old = mkpathdup("%s-%s.pack", packtmp, item->string);
+		stat(fname_old, &statbuffer);
+		statbuffer.st_mode &= ~S_IWOTH;
+		chmod(fname_old, statbuffer.st_mode);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+		free(fname);
+		free(fname_old);
+
+		fname = mkpathdup("%s/pack-%s.idx", packdir, item->string);
+		fname_old = mkpathdup("%s-%s.idx", packtmp, item->string);
+		stat(fname_old, &statbuffer);
+		statbuffer.st_mode &= ~S_IWOTH;
+		chmod(fname_old, statbuffer.st_mode);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+		free(fname);
+		free(fname_old);
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		char *fname;
+		fname = mkpathdup("%s/old-pack-%s.idx", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+		free(fname);
+
+		fname = mkpathdup("%s/old-pack-%s.pack", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+		free(fname);
+	}
+
+	/* End of pack replacement. */
+	if (delete_redundant) {
+		sort_string_list(&names);
+		for_each_string_list_item(item, &existing_packs) {
+			if (!string_list_has_string(&names, item->string))
+				remove_pack(packdir, item->string);
+		}
+		argv_array_clear(&cmd_args);
+		argv_array_push(&cmd_args, "prune-packed");
+		/* TODO: pass argument: ${GIT_QUIET:+-q} */
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = argv_array_detach(&cmd_args, NULL);
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+
+	if (!no_update_server_info) {
+		argv_array_clear(&cmd_args);
+		argv_array_push(&cmd_args, "update-server-info");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = argv_array_detach(&cmd_args, NULL);
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+	return 0;
+}
+
diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
similarity index 100%
rename from git-repack.sh
rename to contrib/examples/git-repack.sh
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.rc3.2.g2c2b664

^ permalink raw reply related	[relevance 6%]

* [RFC PATCHv4] repack: rewrite the shell script in C.
  @ 2013-08-18 22:26  6% ` Stefan Beller
  2013-08-19 23:23  6%   ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2013-08-18 22:26 UTC (permalink / raw)
  To: git, l.s.r, mfick, apelisse, Matthieu.Moy, pclouds, iveqy,
	gitster, mackyle
  Cc: Stefan Beller

This is the beginning of the rewrite of the repacking.

 * rename get_pack_sha1_list to get_pack_filename_list, which
 * reads the pack directory only once as suggested by Rene.
 * fix the grammar as suggested by Kyle.

All tests have been positive at least once now.
However there is still one non-deterministic error occuring,
I am tired to search for it now, I'll get it working tommorow.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                                        |   2 +-
 builtin.h                                       |   1 +
 builtin/repack.c                                | 372 ++++++++++++++++++++++++
 git-repack.sh => contrib/examples/git-repack.sh |   0
 git.c                                           |   1 +
 5 files changed, 375 insertions(+), 1 deletion(-)
 create mode 100644 builtin/repack.c
 rename git-repack.sh => contrib/examples/git-repack.sh (100%)

diff --git a/Makefile b/Makefile
index ef442eb..4ec5bbe 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -972,6 +971,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..bfaaad7
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,372 @@
+/*
+ * The shell version was written by Linus Torvalds (2005) and many others.
+ * This is a translation into C by Stefan Beller (2013)
+ */
+
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+
+#include "argv-array.h"
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+/* enabled by default since 22c79eab (2008-06-25) */
+static int delta_base_offset = 1;
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+static void remove_temporary_files() {
+	DIR *dir;
+	struct dirent *e;
+	char *prefix, *path;
+
+	prefix = mkpathdup(".tmp-%d-pack", getpid());
+	path = mkpathdup("%s/pack", get_object_directory());
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!prefixcmp(e->d_name, prefix)) {
+			struct strbuf fname = STRBUF_INIT;
+			strbuf_addf(&fname, "%s/%s", path, e->d_name);
+			unlink(strbuf_detach(&fname, NULL));
+		}
+	}
+	free(prefix);
+	free(path);
+	closedir(dir);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+/*
+ * Fills the filename list with all the files found in the pack directory
+ * ending with .pack, without that extension.
+ */
+void get_pack_filenames(char *packdir, struct string_list *fname_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *path, *suffix, *fname;
+
+	path = mkpathdup("%s/pack", get_object_directory());
+	suffix = ".pack";
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!suffixcmp(e->d_name, suffix)) {
+			size_t len = strlen(e->d_name) - strlen(suffix);
+			fname = xmemdupz(e->d_name, len);
+			string_list_append_nodup(fname_list, fname);
+		}
+	}
+	free(path);
+	closedir(dir);
+}
+
+/*
+ * remove_pack will remove any files following the pattern *${SHA1}.{EXT}
+ * where EXT is one of {pack, idx, keep}. The SHA1 consists of 40 chars and
+ * is specified by the sha1 parameter.
+ * path is specifying the directory in which all found files will be deleted.
+ */
+void remove_pack(char *path, char* sha1)
+{
+	char *exts[] = {".pack", ".idx",".keep"};
+	char *fname;
+	int ext = 0;
+	for (ext = 0; ext < 3; ext++) {
+		fname = mkpathdup("%s/%s%s", path, sha1, exts[ext]);
+		unlink(fname);
+		free(fname);
+	}
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix) {
+
+	int pack_everything = 0;
+	int pack_everything_but_loose = 0;
+	int delete_redundant = 0;
+	char *unpack_unreachable = NULL;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+	char *packdir, *packtmp;
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	struct stat statbuffer;
+
+	struct option builtin_repack_options[] = {
+		OPT_BOOL('a', "all", &pack_everything,
+				N_("pack everything in a single pack")),
+		OPT_BOOL('A', "all-but-loose", &pack_everything_but_loose,
+				N_("same as -a, and turn unreachable objects loose")),
+		OPT_BOOL('d', "delete-redundant", &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', "no-reuse-delta", &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', "no-reuse-object", &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
+				N_("with -A, do not loosen objects older than this Packing constraints")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	packdir = mkpathdup("%s/pack", get_object_directory());
+	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, getpid());
+
+	remove_temporary_files();
+
+	struct argv_array cmd_args = ARGV_ARRAY_INIT;
+	argv_array_push(&cmd_args, "pack-objects");
+	argv_array_push(&cmd_args, "--keep-true-parents");
+	argv_array_push(&cmd_args, "--honor-pack-keep");
+	argv_array_push(&cmd_args, "--non-empty");
+	argv_array_push(&cmd_args, "--all");
+	argv_array_push(&cmd_args, "--reflog");
+
+	if (window)
+		argv_array_pushf(&cmd_args, "--window=%u", window);
+
+	if (window_memory)
+		argv_array_pushf(&cmd_args, "--window-memory=%u", window_memory);
+
+	if (depth)
+		argv_array_pushf(&cmd_args, "--depth=%u", depth);
+
+	if (max_pack_size)
+		argv_array_pushf(&cmd_args, "--max_pack_size=%u", max_pack_size);
+
+	if (pack_everything + pack_everything_but_loose == 0) {
+		argv_array_push(&cmd_args, "--unpacked");
+		argv_array_push(&cmd_args, "--incremental");
+	} else {
+		if (pack_everything_but_loose && delete_redundant)
+			argv_array_push(&cmd_args, "--unpack-unreachable");
+
+		struct string_list fname_list = STRING_LIST_INIT_DUP;
+		get_pack_filenames(packdir, &fname_list);
+		for_each_string_list_item(item, &fname_list) {
+			char *fname;
+			fname = mkpathdup("%s/%s.keep", packdir, item->string);
+			if (stat(fname, &statbuffer) && S_ISREG(statbuffer.st_mode)) {
+				/* when the keep file is there, we're ignoring that pack */
+			} else {
+				string_list_append(&existing_packs, item->string);
+			}
+			free(fname);
+		}
+
+		if (existing_packs.nr && unpack_unreachable && delete_redundant) {
+			argv_array_pushf(&cmd_args, "--unpack-unreachable=%s", unpack_unreachable);
+		}
+	}
+
+	if (local)
+		argv_array_push(&cmd_args,  "--local");
+
+	if (delta_base_offset)
+		argv_array_push(&cmd_args,  "--delta-base-offset");
+
+	argv_array_push(&cmd_args, packtmp);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = argv_array_detach(&cmd_args, NULL);
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	if (run_command(&cmd))
+		return 1;
+
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_DUP;
+
+	char line[1024];
+	int counter = 0;
+	FILE *out = xfdopen(cmd.out, "r");
+	while (fgets(line, sizeof(line), out)) {
+		/* a line consists of 40 hex chars + '\n' */
+		assert(strlen(line) == 41);
+		line[40] = '\0';
+		string_list_append(&names, line);
+		counter++;
+	}
+	if (!counter)
+		printf("Nothing new to pack.\n");
+	fclose(out);
+
+	char *exts[2] = {".idx", ".pack"};
+	int failed = 0;
+	for_each_string_list_item(item, &names) {
+		int ext;
+		for (ext = 0; ext < 1; ext++) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s%s", packdir, item->string, exts[ext]);
+			if (!file_exists(fname)) {
+				free(fname);
+				continue;
+			}
+
+			fname_old = mkpathdup("%s/old-%s%s", packdir, item->string, exts[ext]);
+			if (file_exists(fname_old))
+				unlink(fname_old);
+
+			if (rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			string_list_append_nodup(&rollback, fname);
+		}
+		if (failed)
+			/* set to last element to break for_each loop */
+			item = names.items + names.nr;
+	}
+	if (failed) {
+		struct string_list rollback_failure;
+		for_each_string_list_item(item, &rollback) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s", packdir, item->string);
+			fname_old = mkpathdup("%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+			free(fname);
+			free(fname_old);
+		}
+
+		if (rollback.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and the\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in $PACKDIR manually:\n");
+			for (i = 0; i < rollback.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback.items[i].string,
+					rollback.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	for_each_string_list_item(item, &names) {
+		char *fname, *fname_old;
+		fname = mkpathdup("%s/pack-%s.pack", packdir, item->string);
+		fname_old = mkpathdup("%s-%s.pack", packtmp, item->string);
+		stat(fname_old, &statbuffer);
+		statbuffer.st_mode &= ~S_IWOTH;
+		chmod(fname_old, statbuffer.st_mode);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+		free(fname);
+		free(fname_old);
+
+		fname = mkpathdup("%s/pack-%s.idx", packdir, item->string);
+		fname_old = mkpathdup("%s-%s.idx", packtmp, item->string);
+		stat(fname_old, &statbuffer);
+		statbuffer.st_mode &= ~S_IWOTH;
+		chmod(fname_old, statbuffer.st_mode);
+		if (rename(fname_old, fname))
+			die("Could not rename packfile: %s -> %s", fname_old, fname);
+		free(fname);
+		free(fname_old);
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		char *fname;
+		fname = mkpathdup("%s/old-pack-%s.idx", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+		free(fname);
+
+		fname = mkpathdup("%s/old-pack-%s.pack", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+		free(fname);
+	}
+
+	/* End of pack replacement. */
+	if (delete_redundant) {
+		sort_string_list(&names);
+		for_each_string_list_item(item, &existing_packs) {
+			char *sha1;
+			size_t len = strlen(item->string);
+			if (len < 40)
+				continue;
+			sha1 = item->string + len - 40;
+			if (!string_list_has_string(&names, sha1))
+				remove_pack(packdir, item->string);
+		}
+		argv_array_clear(&cmd_args);
+		argv_array_push(&cmd_args, "prune-packed");
+		if (quiet)
+			argv_array_push(&cmd_args, "--quiet");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = argv_array_detach(&cmd_args, NULL);
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+
+	if (!no_update_server_info) {
+		argv_array_clear(&cmd_args);
+		argv_array_push(&cmd_args, "update-server-info");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = argv_array_detach(&cmd_args, NULL);
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+	return 0;
+}
+
diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
similarity index 100%
rename from git-repack.sh
rename to contrib/examples/git-repack.sh
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.rc3.2.g2c2b664

^ permalink raw reply related	[relevance 6%]

* [RFC PATCHv4] repack: rewrite the shell script in C.
  2013-08-18 22:26  6% ` [RFC PATCHv4] " Stefan Beller
@ 2013-08-19 23:23  6%   ` Stefan Beller
    0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2013-08-19 23:23 UTC (permalink / raw)
  To: git, l.s.r, mfick, apelisse, Matthieu.Moy, pclouds, iveqy,
	gitster, mackyle
  Cc: Stefan Beller

Hi,

so today I compared the argument lists of the repack shell script with the
C rewrite passed on to the pack-objects command and fixed some corner 
cases (-A -d --unpack-unreachable=%s should only pass 
--unpack-unreachable=%s once to pack-objects)
Also I fixed some missing smaller options (--quiet, --no-reuse-delta, --no-reuse-object).

I have run the test suite several times successfully now,
trying to find a pattern for the non-deterministically bug, which appears to
only occur in 1 out of 4 test suite runs.

The test suite has around 40 calls to repack and 35 calls to gc, which calls
repack internally. That alone covers quite a lot of the repack options,
but the debugging for the test cases is no fun, as the the calls to repack
are usually not the main concern of the respective tests.

There are however 
  t7700-repack.sh 
  t7701-repack-unpack-unreachable.sh
  
It was suggested earlier, and I think it's a good idea to enhance those
tests.

Anyway, here is an updated version of the repack rewrite.

Stefan

--8<--
From f6da16ac3ca71aa746fe6d9224b06e6cc4e7a104 Mon Sep 17 00:00:00 2001
From: Stefan Beller <stefanbeller@googlemail.com>
Date: Fri, 16 Aug 2013 02:08:47 +0200
Subject: [RFC PATCHv4] repack: rewrite the shell script in C.

This is the beginning of the rewrite of the repacking.

All tests have been positive at least once now.
However there is still a non-deterministic error occuring in
about 1 out of 4 test suite runs (usually in 7701 or 9301,
but could also occur in 5501 or 3306 iirc)

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                                        |   2 +-
 builtin.h                                       |   1 +
 builtin/repack.c                                | 363 ++++++++++++++++++++++++
 git-repack.sh => contrib/examples/git-repack.sh |   0
 git.c                                           |   1 +
 5 files changed, 366 insertions(+), 1 deletion(-)
 create mode 100644 builtin/repack.c
 rename git-repack.sh => contrib/examples/git-repack.sh (100%)

diff --git a/Makefile b/Makefile
index ef442eb..4ec5bbe 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -972,6 +971,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..a87900e
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,363 @@
+/*
+ * The shell version was written by Linus Torvalds (2005) and many others.
+ * This is a translation into C by Stefan Beller (2013)
+ */
+
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+#include "argv-array.h"
+
+static int delta_base_offset = 0;
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+static void remove_temporary_files() {
+	DIR *dir;
+	struct dirent *e;
+	char *prefix, *path;
+
+	prefix = mkpathdup(".tmp-%d-pack", getpid());
+	path = mkpathdup("%s/pack", get_object_directory());
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!prefixcmp(e->d_name, prefix)) {
+			struct strbuf fname = STRBUF_INIT;
+			strbuf_addf(&fname, "%s/%s", path, e->d_name);
+			unlink(strbuf_detach(&fname, NULL));
+		}
+	}
+	free(prefix);
+	free(path);
+	closedir(dir);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+/*
+ * Fills the filename list with all the files found in the pack directory
+ * ending with .pack, without that extension.
+ */
+void get_pack_filenames(char *packdir, struct string_list *fname_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *path, *suffix, *fname;
+
+	path = mkpathdup("%s/pack", get_object_directory());
+	suffix = ".pack";
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!suffixcmp(e->d_name, suffix)) {
+			size_t len = strlen(e->d_name) - strlen(suffix);
+			fname = xmemdupz(e->d_name, len);
+			string_list_append_nodup(fname_list, fname);
+		}
+	}
+	free(path);
+	closedir(dir);
+}
+
+void remove_pack(char *path, char* sha1)
+{
+	char *exts[] = {".pack", ".idx", ".keep"};
+	int ext = 0;
+	for (ext = 0; ext < 3; ext++) {
+		char *fname;
+		fname = mkpathdup("%s/%s%s", path, sha1, exts[ext]);
+		unlink(fname);
+		free(fname);
+	}
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix) {
+
+	int pack_everything = 0;
+	int pack_everything_but_loose = 0;
+	int delete_redundant = 0;
+	char *unpack_unreachable = NULL;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+	char *packdir, *packtmp;
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	struct stat statbuffer;
+	int ext;
+	char *exts[2] = {".idx", ".pack"};
+
+	struct option builtin_repack_options[] = {
+		OPT_BOOL('a', "all", &pack_everything,
+				N_("pack everything in a single pack")),
+		OPT_BOOL('A', "all-but-loose", &pack_everything_but_loose,
+				N_("same as -a, and turn unreachable objects loose")),
+		OPT_BOOL('d', "delete-redundant", &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', "no-reuse-delta", &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', "no-reuse-object", &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
+				N_("with -A, do not loosen objects older than this Packing constraints")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	packdir = mkpathdup("%s/pack", get_object_directory());
+	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, getpid());
+
+	remove_temporary_files();
+
+	struct argv_array cmd_args = ARGV_ARRAY_INIT;
+	argv_array_push(&cmd_args, "pack-objects");
+	argv_array_push(&cmd_args, "--keep-true-parents");
+	argv_array_push(&cmd_args, "--honor-pack-keep");
+	argv_array_push(&cmd_args, "--non-empty");
+	argv_array_push(&cmd_args, "--all");
+	argv_array_push(&cmd_args, "--reflog");
+
+	if (window)
+		argv_array_pushf(&cmd_args, "--window=%u", window);
+
+	if (window_memory)
+		argv_array_pushf(&cmd_args, "--window-memory=%u", window_memory);
+
+	if (depth)
+		argv_array_pushf(&cmd_args, "--depth=%u", depth);
+
+	if (max_pack_size)
+		argv_array_pushf(&cmd_args, "--max_pack_size=%u", max_pack_size);
+
+	if (no_reuse_delta)
+		argv_array_pushf(&cmd_args, "--no-reuse-delta");
+
+	if (no_reuse_object)
+		argv_array_pushf(&cmd_args, "--no-reuse-object");
+
+	if (pack_everything + pack_everything_but_loose == 0) {
+		argv_array_push(&cmd_args, "--unpacked");
+		argv_array_push(&cmd_args, "--incremental");
+	} else {
+		struct string_list fname_list = STRING_LIST_INIT_DUP;
+		get_pack_filenames(packdir, &fname_list);
+		for_each_string_list_item(item, &fname_list) {
+			char *fname;
+			fname = mkpathdup("%s/%s.keep", packdir, item->string);
+			if (stat(fname, &statbuffer) && S_ISREG(statbuffer.st_mode)) {
+				/* when the keep file is there, we're ignoring that pack */
+			} else {
+				string_list_append(&existing_packs, item->string);
+			}
+			free(fname);
+		}
+
+		if (existing_packs.nr && delete_redundant) {
+			if (unpack_unreachable)
+				argv_array_pushf(&cmd_args, "--unpack-unreachable=%s", unpack_unreachable);
+			else if (pack_everything_but_loose)
+				argv_array_push(&cmd_args, "--unpack-unreachable");
+		}
+	}
+
+	if (local)
+		argv_array_push(&cmd_args,  "--local");
+	if (quiet)
+		argv_array_push(&cmd_args,  "--quiet");
+	if (delta_base_offset)
+		argv_array_push(&cmd_args,  "--delta-base-offset");
+
+	argv_array_push(&cmd_args, packtmp);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = argv_array_detach(&cmd_args, NULL);
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	if (run_command(&cmd))
+		return 1;
+
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_DUP;
+
+	char line[1024];
+	int counter = 0;
+	FILE *out = xfdopen(cmd.out, "r");
+	while (fgets(line, sizeof(line), out)) {
+		/* a line consists of 40 hex chars + '\n' */
+		assert(strlen(line) == 41);
+		line[40] = '\0';
+		string_list_append(&names, line);
+		counter++;
+	}
+	if (!counter)
+		printf("Nothing new to pack.\n");
+	fclose(out);
+
+	int failed = 0;
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 1; ext++) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s%s", packdir, item->string, exts[ext]);
+			if (!file_exists(fname)) {
+				free(fname);
+				continue;
+			}
+
+			fname_old = mkpathdup("%s/old-%s%s", packdir, item->string, exts[ext]);
+			if (file_exists(fname_old))
+				unlink(fname_old);
+
+			if (rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			free(fname_old);
+			string_list_append_nodup(&rollback, fname);
+		}
+		if (failed)
+			/* set to last element to break for_each loop */
+			item = names.items + names.nr;
+	}
+	if (failed) {
+		struct string_list rollback_failure;
+		for_each_string_list_item(item, &rollback) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s", packdir, item->string);
+			fname_old = mkpathdup("%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+			free(fname);
+			free(fname_old);
+		}
+
+		if (rollback.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and the\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in $PACKDIR manually:\n");
+			for (i = 0; i < rollback.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback.items[i].string,
+					rollback.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/pack-%s%s", packdir, item->string, exts[ext]);
+			fname_old = mkpathdup("%s-%s%s", packtmp, item->string, exts[ext]);
+			stat(fname_old, &statbuffer);
+			statbuffer.st_mode &= ~S_IWUSR | ~S_IWGRP | ~S_IWOTH;
+			chmod(fname_old, statbuffer.st_mode);
+			if (rename(fname_old, fname))
+				die("Could not rename packfile: %s -> %s", fname_old, fname);
+			free(fname);
+			free(fname_old);
+		}
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		char *fname;
+		fname = mkpathdup("%s/old-pack-%s.idx", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+		free(fname);
+
+		fname = mkpathdup("%s/old-pack-%s.pack", packdir, item->string);
+		if (remove_path(fname))
+			die("Could not remove file: %s", fname);
+		free(fname);
+	}
+
+	/* End of pack replacement. */
+	if (delete_redundant) {
+		sort_string_list(&names);
+		for_each_string_list_item(item, &existing_packs) {
+			char *sha1;
+			size_t len = strlen(item->string);
+			if (len < 40)
+				continue;
+			sha1 = item->string + len - 40;
+			if (!string_list_has_string(&names, sha1))
+				remove_pack(packdir, item->string);
+		}
+		argv_array_clear(&cmd_args);
+		argv_array_push(&cmd_args, "prune-packed");
+		if (quiet)
+			argv_array_push(&cmd_args, "--quiet");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = argv_array_detach(&cmd_args, NULL);
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+
+	if (!no_update_server_info) {
+		argv_array_clear(&cmd_args);
+		argv_array_push(&cmd_args, "update-server-info");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = argv_array_detach(&cmd_args, NULL);
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+	return 0;
+}
diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
similarity index 100%
rename from git-repack.sh
rename to contrib/examples/git-repack.sh
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.rc3.1.gc1ebd90

^ permalink raw reply related	[relevance 6%]

* [PATCH] repack: rewrite the shell script in C.
  @ 2013-08-20 22:38  6% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-08-20 22:38 UTC (permalink / raw)
  To: git, mfick, apelisse, Matthieu.Moy, pclouds, iveqy, gitster,
	mackyle, j6t
  Cc: Stefan Beller

This is the beginning of the rewrite of the repacking.
All tests are constantly positive now.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                                        |   2 +-
 builtin.h                                       |   1 +
 builtin/repack.c                                | 361 ++++++++++++++++++++++++
 git-repack.sh => contrib/examples/git-repack.sh |   0
 git.c                                           |   1 +
 5 files changed, 364 insertions(+), 1 deletion(-)
 create mode 100644 builtin/repack.c
 rename git-repack.sh => contrib/examples/git-repack.sh (100%)

diff --git a/Makefile b/Makefile
index ef442eb..4ec5bbe 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -972,6 +971,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..9fbe636
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,361 @@
+/*
+ * The shell version was written by Linus Torvalds (2005) and many others.
+ * This is a translation into C by Stefan Beller (2013)
+ */
+
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+#include "argv-array.h"
+
+static int delta_base_offset = 0;
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+static void remove_temporary_files() {
+	DIR *dir;
+	struct dirent *e;
+	char *prefix, *path;
+
+	prefix = mkpathdup(".tmp-%d-pack", getpid());
+	path = mkpathdup("%s/pack", get_object_directory());
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!prefixcmp(e->d_name, prefix)) {
+			struct strbuf fname = STRBUF_INIT;
+			strbuf_addf(&fname, "%s/%s", path, e->d_name);
+			unlink(strbuf_detach(&fname, NULL));
+		}
+	}
+	free(prefix);
+	free(path);
+	closedir(dir);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+/*
+ * Fills the filename list with all the files found in the pack directory
+ * ending with .pack, without that extension.
+ */
+void get_pack_filenames(char *packdir, struct string_list *fname_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *path, *suffix, *fname;
+
+	path = mkpath("%s/pack", get_object_directory());
+	suffix = ".pack";
+
+	dir = opendir(path);
+	while ((e = readdir(dir)) != NULL) {
+		if (!suffixcmp(e->d_name, suffix)) {
+			size_t len = strlen(e->d_name) - strlen(suffix);
+			fname = xmemdupz(e->d_name, len);
+			string_list_append_nodup(fname_list, fname);
+		}
+	}
+	closedir(dir);
+}
+
+void remove_pack(char *path, char* sha1)
+{
+	char *exts[] = {".pack", ".idx", ".keep"};
+	int ext = 0;
+	for (ext = 0; ext < 3; ext++) {
+		char *fname;
+		fname = mkpath("%s/%s%s", path, sha1, exts[ext]);
+		unlink(fname);
+	}
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix) {
+
+	char *exts[2] = {".idx", ".pack"};
+	char *packdir, *packtmp, line[1024];
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct argv_array cmd_args = ARGV_ARRAY_INIT;
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_DUP;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	int count_packs, ext;
+	FILE *out;
+
+	/* variables to be filled by option parsing */
+	int pack_everything = 0;
+	int pack_everything_but_loose = 0;
+	int delete_redundant = 0;
+	char *unpack_unreachable = NULL;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+
+	struct option builtin_repack_options[] = {
+		OPT_BOOL('a', NULL, &pack_everything,
+				N_("pack everything in a single pack")),
+		OPT_BOOL('A', NULL, &pack_everything_but_loose,
+				N_("same as -a, and turn unreachable objects loose")),
+		OPT_BOOL('d', NULL, &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', NULL, &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', NULL, &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
+				N_("with -A, do not loosen objects older than this Packing constraints")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	packdir = mkpathdup("%s/pack", get_object_directory());
+	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, getpid());
+
+	argv_array_push(&cmd_args, "pack-objects");
+	argv_array_push(&cmd_args, "--keep-true-parents");
+	argv_array_push(&cmd_args, "--honor-pack-keep");
+	argv_array_push(&cmd_args, "--non-empty");
+	argv_array_push(&cmd_args, "--all");
+	argv_array_push(&cmd_args, "--reflog");
+
+	if (window)
+		argv_array_pushf(&cmd_args, "--window=%u", window);
+
+	if (window_memory)
+		argv_array_pushf(&cmd_args, "--window-memory=%u", window_memory);
+
+	if (depth)
+		argv_array_pushf(&cmd_args, "--depth=%u", depth);
+
+	if (max_pack_size)
+		argv_array_pushf(&cmd_args, "--max_pack_size=%u", max_pack_size);
+
+	if (no_reuse_delta)
+		argv_array_pushf(&cmd_args, "--no-reuse-delta");
+
+	if (no_reuse_object)
+		argv_array_pushf(&cmd_args, "--no-reuse-object");
+
+	if (pack_everything + pack_everything_but_loose == 0) {
+		argv_array_push(&cmd_args, "--unpacked");
+		argv_array_push(&cmd_args, "--incremental");
+	} else {
+		struct string_list fname_list = STRING_LIST_INIT_DUP;
+		get_pack_filenames(packdir, &fname_list);
+		for_each_string_list_item(item, &fname_list) {
+			char *fname;
+			fname = mkpathdup("%s/%s.keep", packdir, item->string);
+			if (file_exists(fname)) {
+				/* when the keep file is there, we're ignoring that pack */
+			} else {
+				string_list_append(&existing_packs, item->string);
+			}
+			free(fname);
+		}
+
+		if (existing_packs.nr && delete_redundant) {
+			if (unpack_unreachable)
+				argv_array_pushf(&cmd_args, "--unpack-unreachable=%s", unpack_unreachable);
+			else if (pack_everything_but_loose)
+				argv_array_push(&cmd_args, "--unpack-unreachable");
+		}
+	}
+
+	if (local)
+		argv_array_push(&cmd_args,  "--local");
+	if (quiet)
+		argv_array_push(&cmd_args,  "--quiet");
+	if (delta_base_offset)
+		argv_array_push(&cmd_args,  "--delta-base-offset");
+
+	argv_array_push(&cmd_args, packtmp);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = cmd_args.argv;
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	if (start_command(&cmd))
+		return 1;
+
+	count_packs = 0;
+	out = xfdopen(cmd.out, "r");
+	while (fgets(line, sizeof(line), out)) {
+		/* a line consists of 40 hex chars + '\n' */
+		if (strlen(line) != 41)
+			die("repack: Expecting 40 character sha1 lines only from pack-objects.");
+		line[40] = '\0';
+		string_list_append(&names, line);
+		count_packs++;
+	}
+	if (finish_command(&cmd))
+		return 1;
+	fclose(out);
+
+	if (!count_packs && !quiet)
+		printf("Nothing new to pack.\n");
+
+	int failed = 0;
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s%s", packdir, item->string, exts[ext]);
+			if (!file_exists(fname)) {
+				free(fname);
+				continue;
+			}
+
+			fname_old = mkpath("%s/old-%s%s", packdir, item->string, exts[ext]);
+			if (file_exists(fname_old))
+				unlink(fname_old);
+
+			if (rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			string_list_append_nodup(&rollback, fname);
+			free(fname);
+		}
+		if (failed)
+			break;
+	}
+	if (failed) {
+		struct string_list rollback_failure;
+		for_each_string_list_item(item, &rollback) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s", packdir, item->string);
+			fname_old = mkpath("%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+			free(fname);
+		}
+
+		if (rollback.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and the\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in $PACKDIR manually:\n");
+			for (i = 0; i < rollback.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback.items[i].string,
+					rollback.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			struct stat statbuffer;
+			fname = mkpathdup("%s/pack-%s%s", packdir, item->string, exts[ext]);
+			fname_old = mkpath("%s-%s%s", packtmp, item->string, exts[ext]);
+			if (!stat(fname_old, &statbuffer)) {
+				statbuffer.st_mode &= ~S_IWUSR | ~S_IWGRP | ~S_IWOTH;
+				chmod(fname_old, statbuffer.st_mode);
+			}
+			if (rename(fname_old, fname))
+				die_errno(_("renaming '%s' failed"), fname_old);
+			free(fname);
+		}
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		char *fname;
+		fname = mkpath("%s/old-pack-%s.idx", packdir, item->string);
+		if (remove_path(fname))
+			die_errno(_("removing '%s' failed"), fname);
+
+		fname = mkpath("%s/old-pack-%s.pack", packdir, item->string);
+		if (remove_path(fname))
+			die_errno(_("removing '%s' failed"), fname);
+	}
+
+	/* End of pack replacement. */
+
+	if (delete_redundant) {
+		sort_string_list(&names);
+		for_each_string_list_item(item, &existing_packs) {
+			char *sha1;
+			size_t len = strlen(item->string);
+			if (len < 40)
+				continue;
+			sha1 = item->string + len - 40;
+			if (!string_list_has_string(&names, sha1))
+				remove_pack(packdir, item->string);
+		}
+		argv_array_clear(&cmd_args);
+		argv_array_push(&cmd_args, "prune-packed");
+		if (quiet)
+			argv_array_push(&cmd_args, "--quiet");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args.argv;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+
+	if (!no_update_server_info) {
+		argv_array_clear(&cmd_args);
+		argv_array_push(&cmd_args, "update-server-info");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args.argv;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+	}
+	return 0;
+}
diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
similarity index 100%
rename from git-repack.sh
rename to contrib/examples/git-repack.sh
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.rc3.1.gc1ebd90

^ permalink raw reply related	[relevance 6%]

* [RFC PATCHv6 1/2] repack: rewrite the shell script in C
  @ 2013-08-21 17:28  6% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-08-21 17:28 UTC (permalink / raw)
  To: git, mfick, apelisse, Matthieu.Moy, pclouds, iveqy, gitster,
	mackyle, j6t
  Cc: Stefan Beller

The motivation of this patch is to get closer to a goal of being
able to have a core subset of git functionality built in to git.
That would mean

 * people on Windows could get a copy of at least the core parts
   of Git without having to install a Unix-style shell

 * people deploying to servers don't have to rewrite the #! line
   or worry about the PATH and quality of installed POSIX
   utilities, if they are only using the built-in part written
   in C

This patch is meant to be mostly a literal translation of the
git-repack script; the intent is that later patches would start using
more library facilities, but this patch is meant to be as close to a
no-op as possible so it doesn't do that kind of thing.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                                        |   2 +-
 builtin.h                                       |   1 +
 builtin/repack.c                                | 376 ++++++++++++++++++++++++
 git-repack.sh => contrib/examples/git-repack.sh |   0
 git.c                                           |   1 +
 5 files changed, 379 insertions(+), 1 deletion(-)
 create mode 100644 builtin/repack.c
 rename git-repack.sh => contrib/examples/git-repack.sh (100%)

diff --git a/Makefile b/Makefile
index ef442eb..4ec5bbe 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -972,6 +971,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..fb050c0
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,376 @@
+/*
+ * The shell version was written by Linus Torvalds (2005) and many others.
+ * This is a translation into C by Stefan Beller (2013)
+ */
+
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+#include "argv-array.h"
+
+/* enabled by default since 22c79eab (2008-06-25) */
+static int delta_base_offset = 1;
+char *packdir;
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+/*
+ * Remove temporary $GIT_OBJECT_DIRECTORY/pack/.tmp-$$-pack-* files.
+ */
+static void remove_temporary_files(void)
+{
+	struct strbuf buf = STRBUF_INIT;
+	size_t dirlen, prefixlen;
+	DIR *dir;
+	struct dirent *e;
+
+	/* .git/objects/pack */
+	strbuf_addstr(&buf, get_object_directory());
+	strbuf_addstr(&buf, "/pack");
+	dir = opendir(buf.buf);
+	if (!dir) {
+		strbuf_release(&buf);
+		return;
+	}
+
+	/* .git/objects/pack/.tmp-$$-pack-* */
+	dirlen = buf.len + 1;
+	strbuf_addf(&buf, "/.tmp-%d-pack-", (int)getpid());
+	prefixlen = buf.len - dirlen;
+
+	while ((e = readdir(dir))) {
+		if (strncmp(e->d_name, buf.buf + dirlen, prefixlen))
+			continue;
+		strbuf_setlen(&buf, dirlen);
+		strbuf_addstr(&buf, e->d_name);
+		unlink(buf.buf);
+	}
+	closedir(dir);
+	strbuf_release(&buf);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+static void get_pack_filenames(struct string_list *fname_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *fname;
+
+	if (!(dir = opendir(packdir)))
+		return;
+
+	while ((e = readdir(dir)) != NULL) {
+		if (suffixcmp(e->d_name, ".pack"))
+			continue;
+
+		size_t len = strlen(e->d_name) - strlen(".pack");
+		fname = xmemdupz(e->d_name, len);
+
+		if (!file_exists(mkpath("%s/%s.keep", packdir, fname)))
+			string_list_append_nodup(fname_list, fname);
+	}
+	closedir(dir);
+}
+
+static void remove_redundant_pack(const char *path, const char *sha1)
+{
+	const char *exts[] = {".pack", ".idx", ".keep"};
+	int i;
+	struct strbuf buf = STRBUF_INIT;
+	size_t plen;
+
+	strbuf_addf(&buf, "%s/%s", path, sha1);
+	plen = buf.len;
+
+	for (i = 0; i < ARRAY_SIZE(exts); i++) {
+		strbuf_setlen(&buf, plen);
+		strbuf_addstr(&buf, exts[i]);
+		unlink(buf.buf);
+	}
+}
+
+int cmd_repack(int argc, const char **argv, const char *prefix)
+{
+	const char *exts[2] = {".idx", ".pack"};
+	char *packtmp;
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct argv_array cmd_args = ARGV_ARRAY_INIT;
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_DUP;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	struct strbuf line = STRBUF_INIT;
+	int count_packs, ext, ret;
+	FILE *out;
+
+	/* variables to be filled by option parsing */
+	int pack_everything = 0;
+	int pack_everything_but_loose = 0;
+	int delete_redundant = 0;
+	char *unpack_unreachable = NULL;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+
+	struct option builtin_repack_options[] = {
+		OPT_BOOL('a', NULL, &pack_everything,
+				N_("pack everything in a single pack")),
+		OPT_BOOL('A', NULL, &pack_everything_but_loose,
+				N_("same as -a, and turn unreachable objects loose")),
+		OPT_BOOL('d', NULL, &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', NULL, &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', NULL, &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
+				N_("with -A, do not loosen objects older than this")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	packdir = mkpathdup("%s/pack", get_object_directory());
+	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
+
+	argv_array_push(&cmd_args, "pack-objects");
+	argv_array_push(&cmd_args, "--keep-true-parents");
+	argv_array_push(&cmd_args, "--honor-pack-keep");
+	argv_array_push(&cmd_args, "--non-empty");
+	argv_array_push(&cmd_args, "--all");
+	argv_array_push(&cmd_args, "--reflog");
+	if (window)
+		argv_array_pushf(&cmd_args, "--window=%u", window);
+	if (window_memory)
+		argv_array_pushf(&cmd_args, "--window-memory=%u", window_memory);
+	if (depth)
+		argv_array_pushf(&cmd_args, "--depth=%u", depth);
+	if (max_pack_size)
+		argv_array_pushf(&cmd_args, "--max_pack_size=%u", max_pack_size);
+	if (no_reuse_delta)
+		argv_array_pushf(&cmd_args, "--no-reuse-delta");
+	if (no_reuse_object)
+		argv_array_pushf(&cmd_args, "--no-reuse-object");
+
+	if (!pack_everything && !pack_everything_but_loose) {
+		argv_array_push(&cmd_args, "--unpacked");
+		argv_array_push(&cmd_args, "--incremental");
+	} else {
+		get_pack_filenames(&existing_packs);
+
+		if (existing_packs.nr && delete_redundant) {
+			if (unpack_unreachable)
+				argv_array_pushf(&cmd_args,
+						"--unpack-unreachable=%s",
+						unpack_unreachable);
+			else if (pack_everything_but_loose)
+				argv_array_push(&cmd_args,
+						"--unpack-unreachable");
+		}
+	}
+
+	if (local)
+		argv_array_push(&cmd_args,  "--local");
+	if (quiet)
+		argv_array_push(&cmd_args,  "--quiet");
+	if (delta_base_offset)
+		argv_array_push(&cmd_args,  "--delta-base-offset");
+
+	argv_array_push(&cmd_args, packtmp);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = cmd_args.argv;
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	ret = start_command(&cmd);
+	if (ret)
+		return 1;
+
+	count_packs = 0;
+	out = xfdopen(cmd.out, "r");
+	while (strbuf_getline(&line, out, '\n') != EOF) {
+		if (line.len != 40)
+			die("repack: Expecting 40 character sha1 lines only from pack-objects.");
+		strbuf_addstr(&line, "");
+		string_list_append(&names, line.buf);
+		count_packs++;
+	}
+	fclose(out);
+	ret = finish_command(&cmd);
+	if (ret)
+		return 1;
+	argv_array_clear(&cmd_args);
+
+	if (!count_packs && !quiet)
+		printf("Nothing new to pack.\n");
+
+	int failed = 0;
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s%s", packdir,
+						item->string, exts[ext]);
+			if (!file_exists(fname)) {
+				free(fname);
+				continue;
+			}
+
+			fname_old = mkpathdup("%s/old-%s%s", packdir,
+						item->string, exts[ext]);
+			if (file_exists(fname_old))
+				unlink(fname_old);
+
+			if (rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			string_list_append_nodup(&rollback, fname);
+			free(fname);
+			free(fname_old);
+		}
+		if (failed)
+			break;
+	}
+	if (failed) {
+		struct string_list rollback_failure;
+		for_each_string_list_item(item, &rollback) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s", packdir, item->string);
+			fname_old = mkpath("%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+			free(fname);
+		}
+
+		if (rollback.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and the\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in %s manually:\n", packdir);
+			for (i = 0; i < rollback.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback.items[i].string,
+					rollback.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			struct stat statbuffer;
+			fname = mkpathdup("%s/pack-%s%s",
+					packdir, item->string, exts[ext]);
+			fname_old = mkpathdup("%s-%s%s",
+					packtmp, item->string, exts[ext]);
+			if (!stat(fname_old, &statbuffer)) {
+				statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+				chmod(fname_old, statbuffer.st_mode);
+			}
+			if (rename(fname_old, fname))
+				die_errno(_("renaming '%s' failed"), fname_old);
+			free(fname);
+			free(fname_old);
+		}
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname;
+			fname = mkpath("%s/old-pack-%s%s",
+					packdir,
+					item->string,
+					exts[ext]);
+			if (remove_path(fname))
+				warning(_("removing '%s' failed"), fname);
+		}
+	}
+
+	/* End of pack replacement. */
+
+	if (delete_redundant) {
+		sort_string_list(&names);
+		for_each_string_list_item(item, &existing_packs) {
+			char *sha1;
+			size_t len = strlen(item->string);
+			if (len < 40)
+				continue;
+			sha1 = item->string + len - 40;
+			if (!string_list_has_string(&names, sha1))
+				remove_redundant_pack(packdir, item->string);
+		}
+		argv_array_push(&cmd_args, "prune-packed");
+		if (quiet)
+			argv_array_push(&cmd_args, "--quiet");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args.argv;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+		argv_array_clear(&cmd_args);
+	}
+
+	if (!no_update_server_info) {
+		argv_array_push(&cmd_args, "update-server-info");
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args.argv;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+		argv_array_clear(&cmd_args);
+	}
+	return 0;
+}
diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
similarity index 100%
rename from git-repack.sh
rename to contrib/examples/git-repack.sh
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.rc3.1.gc1ebd90

^ permalink raw reply related	[relevance 6%]

* Re: Dokumenting api-paths.txt
  @ 2013-08-22 17:29  4%                 ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2013-08-22 17:29 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jonathan Nieder, git, Johannes Sixt

Stefan Beller <stefanbeller@googlemail.com> writes:

>> git_path is for resolving paths within GIT_DIR, such as
>> git_path("config") and git_path("COMMIT_EDITMSG").
>> 
>> Jonathan
>
> Before we're doing double work, I just wrote down my understanding
> so far. Feel free to tweak it, or remove obvious parts.

> path API
> ========

I am not sure if they deserve to be called "API"; it is just a
set of simple helper functions.

> `mkpath`::
> 	The parameters are in printf format. This function can be
> 	used to construct short-lived filename strings. It is meant
> 	to be used for direct use in system functions such as
> 	dir(mkpath("%s/pack", get_objects_directory())).
> 	The return value is a pointer to such a sanitized filename
> 	string, but it resides in a static buffer, so it will
> 	be overwritten by the next call to mkpath (or other functions?)
> 	This function only does string handling. It doesn't actually
> 	change anything on the filesystem. (This is not Gits mkdir -p)
>
> `mkpathdup`::
> 	The same as mkpath, but the memory is duplicated into a new
> 	buffer, so it is not short-lived, but stays as long as the
> 	caller doesn't free the memory, which the caller is supposed
> 	to do.

Good.

> `xstrdup`::
> 	Duplicates the given string, making the caller responsible
> 	to free the return value. Basically the same as strdup(2)
> 	with errorhandling.
>
> 	I am not sure if this belongs into the path api documentation,
> 	but it's not documented anywhere else.

This does not belong.  It should be grouped together with xmalloc(),
xcalloc(), xrealloc(), etc. and these are not "path" functions.

> `git_path`::
> 	git_path is for resolving paths within GIT_DIR, such as
> 	git_path("config") and git_path("COMMIT_EDITMSG").
> 	This is similar to mkpath, returning a pointer to a static
> 	buffer, which may be overwritten soon.
>
> `git_pathdup`::
> 	The same as git_path, but creating a new buffer. The caller
> 	is responsible to free the returned buffer.

OK.

> `git_path_submodule`::

Similar to git_path() but is run for a submodule specified by the
"path" given as its first parameter.

^ permalink raw reply	[relevance 4%]

* [PATCH 1/2] repack: rewrite the shell script in C
  @ 2013-08-29 20:39  3% ` Stefan Beller
  2013-09-15 11:42  2%   ` René Scharfe
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2013-08-29 20:39 UTC (permalink / raw)
  To: git, gitster; +Cc: Stefan Beller

The motivation of this patch is to get closer to a goal of being
able to have a core subset of git functionality built in to git.
That would mean

 * people on Windows could get a copy of at least the core parts
   of Git without having to install a Unix-style shell

 * people using git in on servers with chrooted environments
   do not need to worry about standard tools lacking for shell
   scripts.

This patch is meant to be mostly a literal translation of the
git-repack script; the intent is that later patches would start using
more library facilities, but this patch is meant to be as close to a
no-op as possible so it doesn't do that kind of thing.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Makefile                                        |   2 +-
 builtin.h                                       |   1 +
 builtin/repack.c                                | 379 ++++++++++++++++++++++++
 git-repack.sh => contrib/examples/git-repack.sh |   0
 git.c                                           |   1 +
 5 files changed, 382 insertions(+), 1 deletion(-)
 create mode 100644 builtin/repack.c
 rename git-repack.sh => contrib/examples/git-repack.sh (100%)

diff --git a/Makefile b/Makefile
index 3588ca1..69e5267 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -971,6 +970,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..0cc823d
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,379 @@
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+#include "argv-array.h"
+
+static int delta_base_offset = 1;
+static char *packdir, *packtmp;
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+/*
+ * Remove temporary $GIT_OBJECT_DIRECTORY/pack/.tmp-$$-pack-* files.
+ */
+static void remove_temporary_files(void)
+{
+	struct strbuf buf = STRBUF_INIT;
+	size_t dirlen, prefixlen;
+	DIR *dir;
+	struct dirent *e;
+
+	dir = opendir(packdir);
+	if (!dir)
+		return;
+
+	strbuf_addstr(&buf, packdir);
+
+	/* Point at the slash at the end of ".../objects/pack/" */
+	dirlen = buf.len + 1;
+	strbuf_addf(&buf, "%s", packtmp);
+	/* Point at the dash at the end of ".../.tmp-%d-pack-" */
+	prefixlen = buf.len - dirlen;
+
+	while ((e = readdir(dir))) {
+		if (strncmp(e->d_name, buf.buf + dirlen, prefixlen))
+			continue;
+		strbuf_setlen(&buf, dirlen);
+		strbuf_addstr(&buf, e->d_name);
+		unlink(buf.buf);
+	}
+	closedir(dir);
+	strbuf_release(&buf);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+/*
+ * Adds all packs hex strings to the fname list, which do not
+ * have a corresponding .keep file.
+ */
+static void get_non_kept_pack_filenames(struct string_list *fname_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *fname;
+	size_t len;
+
+	if (!(dir = opendir(packdir)))
+		return;
+
+	while ((e = readdir(dir)) != NULL) {
+		if (suffixcmp(e->d_name, ".pack"))
+			continue;
+
+		len = strlen(e->d_name) - strlen(".pack");
+		fname = xmemdupz(e->d_name, len);
+
+		if (!file_exists(mkpath("%s/%s.keep", packdir, fname)))
+			string_list_append_nodup(fname_list, fname);
+	}
+	closedir(dir);
+}
+
+static void remove_redundant_pack(const char *path_prefix, const char *hex)
+{
+	const char *exts[] = {".pack", ".idx", ".keep"};
+	int i;
+	struct strbuf buf = STRBUF_INIT;
+	size_t plen;
+
+	strbuf_addf(&buf, "%s/%s", path_prefix, hex);
+	plen = buf.len;
+
+	for (i = 0; i < ARRAY_SIZE(exts); i++) {
+		strbuf_setlen(&buf, plen);
+		strbuf_addstr(&buf, exts[i]);
+		unlink(buf.buf);
+	}
+}
+
+#define ALL_INTO_ONE 1
+#define LOOSE_UNREACHABLE 2
+
+int cmd_repack(int argc, const char **argv, const char *prefix)
+{
+	const char *exts[2] = {".pack", ".idx"};
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct argv_array cmd_args = ARGV_ARRAY_INIT;
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_NODUP;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	struct strbuf line = STRBUF_INIT;
+	int nr_packs, ext, ret, failed;
+	FILE *out;
+
+	/* variables to be filled by option parsing */
+	int pack_everything = 0;
+	int delete_redundant = 0;
+	char *unpack_unreachable = NULL;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+
+	struct option builtin_repack_options[] = {
+		OPT_BIT('a', NULL, &pack_everything,
+				N_("pack everything in a single pack"), ALL_INTO_ONE),
+		OPT_BIT('A', NULL, &pack_everything,
+				N_("same as -a, and turn unreachable objects loose"), LOOSE_UNREACHABLE),
+		OPT_BOOL('d', NULL, &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', NULL, &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', NULL, &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
+				N_("with -A, do not loosen objects older than this")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	packdir = mkpathdup("%s/pack", get_object_directory());
+	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	argv_array_push(&cmd_args, "pack-objects");
+	argv_array_push(&cmd_args, "--keep-true-parents");
+	argv_array_push(&cmd_args, "--honor-pack-keep");
+	argv_array_push(&cmd_args, "--non-empty");
+	argv_array_push(&cmd_args, "--all");
+	argv_array_push(&cmd_args, "--reflog");
+	if (window)
+		argv_array_pushf(&cmd_args, "--window=%u", window);
+	if (window_memory)
+		argv_array_pushf(&cmd_args, "--window-memory=%u", window_memory);
+	if (depth)
+		argv_array_pushf(&cmd_args, "--depth=%u", depth);
+	if (max_pack_size)
+		argv_array_pushf(&cmd_args, "--max_pack_size=%u", max_pack_size);
+	if (no_reuse_delta)
+		argv_array_pushf(&cmd_args, "--no-reuse-delta");
+	if (no_reuse_object)
+		argv_array_pushf(&cmd_args, "--no-reuse-object");
+
+	if (!pack_everything) {
+		argv_array_push(&cmd_args, "--unpacked");
+		argv_array_push(&cmd_args, "--incremental");
+	} else {
+		get_non_kept_pack_filenames(&existing_packs);
+
+		if (existing_packs.nr && delete_redundant) {
+			if (unpack_unreachable)
+				argv_array_pushf(&cmd_args,
+						"--unpack-unreachable=%s",
+						unpack_unreachable);
+			else if (pack_everything & LOOSE_UNREACHABLE)
+				argv_array_push(&cmd_args,
+						"--unpack-unreachable");
+		}
+	}
+
+	if (local)
+		argv_array_push(&cmd_args,  "--local");
+	if (quiet)
+		argv_array_push(&cmd_args,  "--quiet");
+	if (delta_base_offset)
+		argv_array_push(&cmd_args,  "--delta-base-offset");
+
+	argv_array_push(&cmd_args, packtmp);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = cmd_args.argv;
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	ret = start_command(&cmd);
+	if (ret)
+		return 1;
+
+	nr_packs = 0;
+	out = xfdopen(cmd.out, "r");
+	while (strbuf_getline(&line, out, '\n') != EOF) {
+		if (line.len != 40)
+			die("repack: Expecting 40 character sha1 lines only from pack-objects.");
+		string_list_append(&names, line.buf);
+		nr_packs++;
+	}
+	fclose(out);
+	ret = finish_command(&cmd);
+	if (ret)
+		return 1;
+	argv_array_clear(&cmd_args);
+
+	if (!nr_packs && !quiet)
+		printf("Nothing new to pack.\n");
+
+	/*
+	 * Ok we have prepared all new packfiles.
+	 * First see if there are packs of the same name and if so
+	 * if we can move them out of the way (this can happen if we
+	 * repacked immediately after packing fully.
+	 */
+	failed = 0;
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s%s", packdir,
+						item->string, exts[ext]);
+			if (!file_exists(fname)) {
+				free(fname);
+				continue;
+			}
+
+			fname_old = mkpath("%s/old-%s%s", packdir,
+						item->string, exts[ext]);
+			if (file_exists(fname_old))
+				if (unlink(fname_old))
+					failed = 1;
+
+			if (!failed && rename(fname, fname_old)) {
+				failed = 1;
+				break;
+			}
+			string_list_append(&rollback, fname);
+		}
+		if (failed)
+			break;
+	}
+	if (failed) {
+		struct string_list rollback_failure = STRING_LIST_INIT_DUP;
+		for_each_string_list_item(item, &rollback) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s", packdir, item->string);
+			fname_old = mkpath("%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+			free(fname);
+		}
+
+		if (rollback_failure.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and the\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in %s manually:\n", packdir);
+			for (i = 0; i < rollback_failure.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback_failure.items[i].string,
+					rollback_failure.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			struct stat statbuffer;
+			fname = mkpathdup("%s/pack-%s%s",
+					packdir, item->string, exts[ext]);
+			fname_old = mkpathdup("%s-%s%s",
+					packtmp, item->string, exts[ext]);
+			if (!stat(fname_old, &statbuffer)) {
+				statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+				chmod(fname_old, statbuffer.st_mode);
+			}
+			if (rename(fname_old, fname))
+				die_errno(_("renaming '%s' failed"), fname_old);
+			free(fname);
+			free(fname_old);
+		}
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname;
+			fname = mkpath("%s/old-pack-%s%s",
+					packdir,
+					item->string,
+					exts[ext]);
+			if (remove_path(fname))
+				warning(_("removing '%s' failed"), fname);
+		}
+	}
+
+	/* End of pack replacement. */
+
+	if (delete_redundant) {
+		sort_string_list(&names);
+		for_each_string_list_item(item, &existing_packs) {
+			char *sha1;
+			size_t len = strlen(item->string);
+			if (len < 40)
+				continue;
+			sha1 = item->string + len - 40;
+			if (!string_list_has_string(&names, sha1))
+				remove_redundant_pack(packdir, item->string);
+		}
+		argv_array_push(&cmd_args, "prune-packed");
+		if (quiet)
+			argv_array_push(&cmd_args, "--quiet");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args.argv;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+		argv_array_clear(&cmd_args);
+	}
+
+	if (!no_update_server_info) {
+		argv_array_push(&cmd_args, "update-server-info");
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args.argv;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+		argv_array_clear(&cmd_args);
+	}
+	remove_temporary_files();
+	return 0;
+}
diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
similarity index 100%
rename from git-repack.sh
rename to contrib/examples/git-repack.sh
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4

^ permalink raw reply related	[relevance 3%]

* Re: [PATCH 1/2] repack: rewrite the shell script in C
  2013-08-29 20:39  3% ` [PATCH 1/2] repack: rewrite the shell script " Stefan Beller
@ 2013-09-15 11:42  2%   ` René Scharfe
  0 siblings, 0 replies; 200+ results
From: René Scharfe @ 2013-09-15 11:42 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, gitster

Am 29.08.2013 22:39, schrieb Stefan Beller:
> The motivation of this patch is to get closer to a goal of being
> able to have a core subset of git functionality built in to git.
> That would mean
>
>  * people on Windows could get a copy of at least the core parts
>    of Git without having to install a Unix-style shell
>
>  * people using git in on servers with chrooted environments
>    do not need to worry about standard tools lacking for shell
>    scripts.
>
> This patch is meant to be mostly a literal translation of the
> git-repack script; the intent is that later patches would start using
> more library facilities, but this patch is meant to be as close to a
> no-op as possible so it doesn't do that kind of thing.
>
> Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
> ---
>  Makefile                                        |   2 +-
>  builtin.h                                       |   1 +
>  builtin/repack.c                                | 379 ++++++++++++++++++++++++
>  git-repack.sh => contrib/examples/git-repack.sh |   0
>  git.c                                           |   1 +
>  5 files changed, 382 insertions(+), 1 deletion(-)
>  create mode 100644 builtin/repack.c
>  rename git-repack.sh => contrib/examples/git-repack.sh (100%)
>
> diff --git a/Makefile b/Makefile
> index 3588ca1..69e5267 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
>  SCRIPT_SH += git-quiltimport.sh
>  SCRIPT_SH += git-rebase.sh
>  SCRIPT_SH += git-remote-testgit.sh
> -SCRIPT_SH += git-repack.sh
>  SCRIPT_SH += git-request-pull.sh
>  SCRIPT_SH += git-stash.sh
>  SCRIPT_SH += git-submodule.sh
> @@ -971,6 +970,7 @@ BUILTIN_OBJS += builtin/reflog.o
>  BUILTIN_OBJS += builtin/remote.o
>  BUILTIN_OBJS += builtin/remote-ext.o
>  BUILTIN_OBJS += builtin/remote-fd.o
> +BUILTIN_OBJS += builtin/repack.o
>  BUILTIN_OBJS += builtin/replace.o
>  BUILTIN_OBJS += builtin/rerere.o
>  BUILTIN_OBJS += builtin/reset.o
> diff --git a/builtin.h b/builtin.h
> index 8afa2de..b56cf07 100644
> --- a/builtin.h
> +++ b/builtin.h
> @@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
>  extern int cmd_remote(int argc, const char **argv, const char *prefix);
>  extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
>  extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
> +extern int cmd_repack(int argc, const char **argv, const char *prefix);
>  extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
>  extern int cmd_rerere(int argc, const char **argv, const char *prefix);
>  extern int cmd_reset(int argc, const char **argv, const char *prefix);
> diff --git a/builtin/repack.c b/builtin/repack.c
> new file mode 100644
> index 0000000..0cc823d
> --- /dev/null
> +++ b/builtin/repack.c
> @@ -0,0 +1,379 @@
> +#include "builtin.h"
> +#include "cache.h"
> +#include "dir.h"
> +#include "parse-options.h"
> +#include "run-command.h"
> +#include "sigchain.h"
> +#include "strbuf.h"
> +#include "string-list.h"
> +#include "argv-array.h"
> +
> +static int delta_base_offset = 1;
> +static char *packdir, *packtmp;
> +
> +static const char *const git_repack_usage[] = {
> +	N_("git repack [options]"),
> +	NULL
> +};
> +
> +static int repack_config(const char *var, const char *value, void *cb)
> +{
> +	if (!strcmp(var, "repack.usedeltabaseoffset")) {
> +		delta_base_offset = git_config_bool(var, value);
> +		return 0;
> +	}
> +	return git_default_config(var, value, cb);
> +}
> +
> +/*
> + * Remove temporary $GIT_OBJECT_DIRECTORY/pack/.tmp-$$-pack-* files.
> + */
> +static void remove_temporary_files(void)
> +{
> +	struct strbuf buf = STRBUF_INIT;
> +	size_t dirlen, prefixlen;
> +	DIR *dir;
> +	struct dirent *e;
> +
> +	dir = opendir(packdir);
> +	if (!dir)
> +		return;
> +
> +	strbuf_addstr(&buf, packdir);

Let's say packdir is ".git/objects/pack" (no trailing slash).  Then buf 
is ".git/objects/pack" now as well.

> +
> +	/* Point at the slash at the end of ".../objects/pack/" */
> +	dirlen = buf.len + 1;
> +	strbuf_addf(&buf, "%s", packtmp);

packtmp starts with packdir, so by adding it here we have it twice.  buf 
is now ".git/objects/pack.git/objects/pack/.tmp-123-pack" (if our pid is 
123), no?

Perhaps don't add the packdir to the strbuf in the first place and 
calculate dirlen as strlen(packdir) + 1?

Besided, strbuf_addstr(x, y) is better for adding a string than 
strbuf_addf(x, "%s", y).

> +	/* Point at the dash at the end of ".../.tmp-%d-pack-" */
> +	prefixlen = buf.len - dirlen;

This is the length of "git/objects/pack/.tmp-123-pack" now.

> +
> +	while ((e = readdir(dir))) {
> +		if (strncmp(e->d_name, buf.buf + dirlen, prefixlen))
> +			continue;
> +		strbuf_setlen(&buf, dirlen);
> +		strbuf_addstr(&buf, e->d_name);
> +		unlink(buf.buf);
> +	}
> +	closedir(dir);
> +	strbuf_release(&buf);
> +}
> +
> +static void remove_pack_on_signal(int signo)
> +{
> +	remove_temporary_files();
> +	sigchain_pop(signo);
> +	raise(signo);
> +}
> +
> +/*
> + * Adds all packs hex strings to the fname list, which do not
> + * have a corresponding .keep file.
> + */
> +static void get_non_kept_pack_filenames(struct string_list *fname_list)
> +{
> +	DIR *dir;
> +	struct dirent *e;
> +	char *fname;
> +	size_t len;
> +
> +	if (!(dir = opendir(packdir)))
> +		return;
> +
> +	while ((e = readdir(dir)) != NULL) {
> +		if (suffixcmp(e->d_name, ".pack"))
> +			continue;
> +
> +		len = strlen(e->d_name) - strlen(".pack");
> +		fname = xmemdupz(e->d_name, len);
> +
> +		if (!file_exists(mkpath("%s/%s.keep", packdir, fname)))
> +			string_list_append_nodup(fname_list, fname);

This leaks fname for packs with .keep files.

> +	}
> +	closedir(dir);
> +}
> +
> +static void remove_redundant_pack(const char *path_prefix, const char *hex)
> +{
> +	const char *exts[] = {".pack", ".idx", ".keep"};
> +	int i;
> +	struct strbuf buf = STRBUF_INIT;
> +	size_t plen;
> +
> +	strbuf_addf(&buf, "%s/%s", path_prefix, hex);
> +	plen = buf.len;
> +
> +	for (i = 0; i < ARRAY_SIZE(exts); i++) {
> +		strbuf_setlen(&buf, plen);
> +		strbuf_addstr(&buf, exts[i]);
> +		unlink(buf.buf);
> +	}
> +}

hex must also include the "pack-" prefix and path_prefix must be a 
directory name.  Perhaps call them base_name and dir_name or similar to 
make that clearer?

buf is leaked.

> +
> +#define ALL_INTO_ONE 1
> +#define LOOSE_UNREACHABLE 2
> +
> +int cmd_repack(int argc, const char **argv, const char *prefix)
> +{
> +	const char *exts[2] = {".pack", ".idx"};
> +	struct child_process cmd;
> +	struct string_list_item *item;
> +	struct argv_array cmd_args = ARGV_ARRAY_INIT;
> +	struct string_list names = STRING_LIST_INIT_DUP;
> +	struct string_list rollback = STRING_LIST_INIT_NODUP;
> +	struct string_list existing_packs = STRING_LIST_INIT_DUP;
> +	struct strbuf line = STRBUF_INIT;
> +	int nr_packs, ext, ret, failed;
> +	FILE *out;
> +
> +	/* variables to be filled by option parsing */
> +	int pack_everything = 0;
> +	int delete_redundant = 0;
> +	char *unpack_unreachable = NULL;
> +	int window = 0, window_memory = 0;
> +	int depth = 0;
> +	int max_pack_size = 0;
> +	int no_reuse_delta = 0, no_reuse_object = 0;
> +	int no_update_server_info = 0;
> +	int quiet = 0;
> +	int local = 0;
> +
> +	struct option builtin_repack_options[] = {
> +		OPT_BIT('a', NULL, &pack_everything,
> +				N_("pack everything in a single pack"), ALL_INTO_ONE),
> +		OPT_BIT('A', NULL, &pack_everything,
> +				N_("same as -a, and turn unreachable objects loose"), LOOSE_UNREACHABLE),
> +		OPT_BOOL('d', NULL, &delete_redundant,
> +				N_("remove redundant packs, and run git-prune-packed")),
> +		OPT_BOOL('f', NULL, &no_reuse_delta,
> +				N_("pass --no-reuse-delta to git-pack-objects")),
> +		OPT_BOOL('F', NULL, &no_reuse_object,
> +				N_("pass --no-reuse-object to git-pack-objects")),
> +		OPT_BOOL('n', NULL, &no_update_server_info,
> +				N_("do not run git-update-server-info")),
> +		OPT__QUIET(&quiet, N_("be quiet")),
> +		OPT_BOOL('l', "local", &local,
> +				N_("pass --local to git-pack-objects")),
> +		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
> +				N_("with -A, do not loosen objects older than this")),
> +		OPT_INTEGER(0, "window", &window,
> +				N_("size of the window used for delta compression")),
> +		OPT_INTEGER(0, "window-memory", &window_memory,
> +				N_("same as the above, but limit memory size instead of entries count")),
> +		OPT_INTEGER(0, "depth", &depth,
> +				N_("limits the maximum delta depth")),
> +		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
> +				N_("maximum size of each packfile")),
> +		OPT_END()
> +	};
> +
> +	git_config(repack_config, NULL);
> +
> +	argc = parse_options(argc, argv, prefix, builtin_repack_options,
> +				git_repack_usage, 0);
> +
> +	packdir = mkpathdup("%s/pack", get_object_directory());
> +	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
> +
> +	sigchain_push_common(remove_pack_on_signal);
> +
> +	argv_array_push(&cmd_args, "pack-objects");
> +	argv_array_push(&cmd_args, "--keep-true-parents");
> +	argv_array_push(&cmd_args, "--honor-pack-keep");
> +	argv_array_push(&cmd_args, "--non-empty");
> +	argv_array_push(&cmd_args, "--all");
> +	argv_array_push(&cmd_args, "--reflog");
> +	if (window)
> +		argv_array_pushf(&cmd_args, "--window=%u", window);
> +	if (window_memory)
> +		argv_array_pushf(&cmd_args, "--window-memory=%u", window_memory);
> +	if (depth)
> +		argv_array_pushf(&cmd_args, "--depth=%u", depth);
> +	if (max_pack_size)
> +		argv_array_pushf(&cmd_args, "--max_pack_size=%u", max_pack_size);
> +	if (no_reuse_delta)
> +		argv_array_pushf(&cmd_args, "--no-reuse-delta");
> +	if (no_reuse_object)
> +		argv_array_pushf(&cmd_args, "--no-reuse-object");
> +
> +	if (!pack_everything) {
> +		argv_array_push(&cmd_args, "--unpacked");
> +		argv_array_push(&cmd_args, "--incremental");
> +	} else {
> +		get_non_kept_pack_filenames(&existing_packs);
> +
> +		if (existing_packs.nr && delete_redundant) {
> +			if (unpack_unreachable)
> +				argv_array_pushf(&cmd_args,
> +						"--unpack-unreachable=%s",
> +						unpack_unreachable);
> +			else if (pack_everything & LOOSE_UNREACHABLE)
> +				argv_array_push(&cmd_args,
> +						"--unpack-unreachable");
> +		}
> +	}
> +
> +	if (local)
> +		argv_array_push(&cmd_args,  "--local");
> +	if (quiet)
> +		argv_array_push(&cmd_args,  "--quiet");
> +	if (delta_base_offset)
> +		argv_array_push(&cmd_args,  "--delta-base-offset");
> +
> +	argv_array_push(&cmd_args, packtmp);
> +
> +	memset(&cmd, 0, sizeof(cmd));
> +	cmd.argv = cmd_args.argv;
> +	cmd.git_cmd = 1;
> +	cmd.out = -1;
> +	cmd.no_stdin = 1;
> +
> +	ret = start_command(&cmd);
> +	if (ret)
> +		return 1;
> +
> +	nr_packs = 0;
> +	out = xfdopen(cmd.out, "r");
> +	while (strbuf_getline(&line, out, '\n') != EOF) {
> +		if (line.len != 40)
> +			die("repack: Expecting 40 character sha1 lines only from pack-objects.");
> +		string_list_append(&names, line.buf);
> +		nr_packs++;
> +	}
> +	fclose(out);
> +	ret = finish_command(&cmd);
> +	if (ret)
> +		return 1;
> +	argv_array_clear(&cmd_args);
> +
> +	if (!nr_packs && !quiet)
> +		printf("Nothing new to pack.\n");
> +
> +	/*
> +	 * Ok we have prepared all new packfiles.
> +	 * First see if there are packs of the same name and if so
> +	 * if we can move them out of the way (this can happen if we
> +	 * repacked immediately after packing fully.
> +	 */
> +	failed = 0;
> +	for_each_string_list_item(item, &names) {
> +		for (ext = 0; ext < 2; ext++) {
> +			char *fname, *fname_old;
> +			fname = mkpathdup("%s/%s%s", packdir,
> +						item->string, exts[ext]);
> +			if (!file_exists(fname)) {
> +				free(fname);
> +				continue;
> +			}
> +
> +			fname_old = mkpath("%s/old-%s%s", packdir,
> +						item->string, exts[ext]);
> +			if (file_exists(fname_old))
> +				if (unlink(fname_old))
> +					failed = 1;
> +
> +			if (!failed && rename(fname, fname_old)) {
> +				failed = 1;
> +				break;

This leaks fname.

> +			}
> +			string_list_append(&rollback, fname);

Mental note: This is effectively string_list_append_nodup because 
rollback is initialized with STRING_LIST_INIT_NODUP, so there's no leak 
here.

> +		}
> +		if (failed)
> +			break;
> +	}
> +	if (failed) {
> +		struct string_list rollback_failure = STRING_LIST_INIT_DUP;
> +		for_each_string_list_item(item, &rollback) {
> +			char *fname, *fname_old;
> +			fname = mkpathdup("%s/%s", packdir, item->string);
> +			fname_old = mkpath("%s/old-%s", packdir, item->string);
> +			if (rename(fname_old, fname))
> +				string_list_append(&rollback_failure, fname);
> +			free(fname);
> +		}
> +
> +		if (rollback_failure.nr) {
> +			int i;
> +			fprintf(stderr,
> +				"WARNING: Some packs in use have been renamed by\n"
> +				"WARNING: prefixing old- to their name, in order to\n"
> +				"WARNING: replace them with the new version of the\n"
> +				"WARNING: file.  But the operation failed, and the\n"
> +				"WARNING: attempt to rename them back to their\n"
> +				"WARNING: original names also failed.\n"
> +				"WARNING: Please rename them in %s manually:\n", packdir);
> +			for (i = 0; i < rollback_failure.nr; i++)
> +				fprintf(stderr, "WARNING:   old-%s -> %s\n",
> +					rollback_failure.items[i].string,
> +					rollback_failure.items[i].string);
> +		}
> +		exit(1);
> +	}
> +
> +	/* Now the ones with the same name are out of the way... */
> +	for_each_string_list_item(item, &names) {
> +		for (ext = 0; ext < 2; ext++) {
> +			char *fname, *fname_old;
> +			struct stat statbuffer;
> +			fname = mkpathdup("%s/pack-%s%s",
> +					packdir, item->string, exts[ext]);
> +			fname_old = mkpathdup("%s-%s%s",
> +					packtmp, item->string, exts[ext]);
> +			if (!stat(fname_old, &statbuffer)) {
> +				statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
> +				chmod(fname_old, statbuffer.st_mode);
> +			}
> +			if (rename(fname_old, fname))
> +				die_errno(_("renaming '%s' failed"), fname_old);

The Shell script exits silently in that case.  How about improving error 
reporting in a separate patch?

> +			free(fname);
> +			free(fname_old);
> +		}
> +	}
> +
> +	/* Remove the "old-" files */
> +	for_each_string_list_item(item, &names) {
> +		for (ext = 0; ext < 2; ext++) {
> +			char *fname;
> +			fname = mkpath("%s/old-pack-%s%s",
> +					packdir,
> +					item->string,
> +					exts[ext]);
> +			if (remove_path(fname))
> +				warning(_("removing '%s' failed"), fname);

Similar case here: The Shell script continues silently.

> +		}
> +	}
> +
> +	/* End of pack replacement. */
> +
> +	if (delete_redundant) {
> +		sort_string_list(&names);
> +		for_each_string_list_item(item, &existing_packs) {
> +			char *sha1;
> +			size_t len = strlen(item->string);
> +			if (len < 40)
> +				continue;
> +			sha1 = item->string + len - 40;
> +			if (!string_list_has_string(&names, sha1))
> +				remove_redundant_pack(packdir, item->string);
> +		}
> +		argv_array_push(&cmd_args, "prune-packed");
> +		if (quiet)
> +			argv_array_push(&cmd_args, "--quiet");
> +
> +		memset(&cmd, 0, sizeof(cmd));
> +		cmd.argv = cmd_args.argv;
> +		cmd.git_cmd = 1;
> +		run_command(&cmd);
> +		argv_array_clear(&cmd_args);
> +	}
> +
> +	if (!no_update_server_info) {
> +		argv_array_push(&cmd_args, "update-server-info");
> +		memset(&cmd, 0, sizeof(cmd));
> +		cmd.argv = cmd_args.argv;
> +		cmd.git_cmd = 1;
> +		run_command(&cmd);
> +		argv_array_clear(&cmd_args);
> +	}
> +	remove_temporary_files();

If you take care to clear the argv_arrays then perhaps do the same for 
the string_lists?  The OS cleans up after us anyway, but calming 
Valgrind or similar leak checkers is a good practice nevertheless.

> +	return 0;
> +}
> diff --git a/git-repack.sh b/contrib/examples/git-repack.sh
> similarity index 100%
> rename from git-repack.sh
> rename to contrib/examples/git-repack.sh
> diff --git a/git.c b/git.c
> index 2025f77..03510be 100644
> --- a/git.c
> +++ b/git.c
> @@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
>  		{ "remote", cmd_remote, RUN_SETUP },
>  		{ "remote-ext", cmd_remote_ext },
>  		{ "remote-fd", cmd_remote_fd },
> +		{ "repack", cmd_repack, RUN_SETUP },
>  		{ "replace", cmd_replace, RUN_SETUP },
>  		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
>  		{ "rerere", cmd_rerere, RUN_SETUP },
> -- 1.8.4
>

^ permalink raw reply	[relevance 2%]

* [PATCH 1/3] repack: rewrite the shell script in C
@ 2013-09-15 15:33  2% Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-09-15 15:33 UTC (permalink / raw)
  To: gitster, git; +Cc: Stefan Beller

The motivation of this patch is to get closer to a goal of being
able to have a core subset of git functionality built in to git.
That would mean

 * people on Windows could get a copy of at least the core parts
   of Git without having to install a Unix-style shell

 * people using git in on servers with chrooted environments
   do not need to worry about standard tools lacking for shell
   scripts.

This patch is meant to be mostly a literal translation of the
git-repack script; the intent is that later patches would start using
more library facilities, but this patch is meant to be as close to a
no-op as possible so it doesn't do that kind of thing.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Makefile                       |   2 +-
 builtin.h                      |   1 +
 builtin/repack.c               | 387 +++++++++++++++++++++++++++++++++++++++++
 contrib/examples/git-repack.sh | 194 +++++++++++++++++++++
 git-repack.sh                  | 194 ---------------------
 git.c                          |   1 +
 6 files changed, 584 insertions(+), 195 deletions(-)
 create mode 100644 builtin/repack.c
 create mode 100755 contrib/examples/git-repack.sh
 delete mode 100755 git-repack.sh

diff --git a/Makefile b/Makefile
index 3588ca1..69e5267 100644
--- a/Makefile
+++ b/Makefile
@@ -464,7 +464,6 @@ SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
-SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
@@ -971,6 +970,7 @@ BUILTIN_OBJS += builtin/reflog.o
 BUILTIN_OBJS += builtin/remote.o
 BUILTIN_OBJS += builtin/remote-ext.o
 BUILTIN_OBJS += builtin/remote-fd.o
+BUILTIN_OBJS += builtin/repack.o
 BUILTIN_OBJS += builtin/replace.o
 BUILTIN_OBJS += builtin/rerere.o
 BUILTIN_OBJS += builtin/reset.o
diff --git a/builtin.h b/builtin.h
index 8afa2de..b56cf07 100644
--- a/builtin.h
+++ b/builtin.h
@@ -102,6 +102,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);
 extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
+extern int cmd_repack(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
 extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_reset(int argc, const char **argv, const char *prefix);
diff --git a/builtin/repack.c b/builtin/repack.c
new file mode 100644
index 0000000..a15bd9b
--- /dev/null
+++ b/builtin/repack.c
@@ -0,0 +1,387 @@
+#include "builtin.h"
+#include "cache.h"
+#include "dir.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "strbuf.h"
+#include "string-list.h"
+#include "argv-array.h"
+
+static int delta_base_offset = 1;
+static char *packdir, *packtmp;
+
+static const char *const git_repack_usage[] = {
+	N_("git repack [options]"),
+	NULL
+};
+
+static int repack_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "repack.usedeltabaseoffset")) {
+		delta_base_offset = git_config_bool(var, value);
+		return 0;
+	}
+	return git_default_config(var, value, cb);
+}
+
+/*
+ * Remove temporary $GIT_OBJECT_DIRECTORY/pack/.tmp-$$-pack-* files.
+ */
+static void remove_temporary_files(void)
+{
+	struct strbuf buf = STRBUF_INIT;
+	size_t dirlen, prefixlen;
+	DIR *dir;
+	struct dirent *e;
+
+	dir = opendir(packdir);
+	if (!dir)
+		return;
+
+	/* Point at the slash at the end of ".../objects/pack/" */
+	dirlen = strlen(packdir) + 1;
+	strbuf_addstr(&buf, packtmp);
+	/* Hold the length of  ".tmp-%d-pack-" */
+	prefixlen = buf.len - dirlen;
+
+	while ((e = readdir(dir))) {
+		if (strncmp(e->d_name, buf.buf + dirlen, prefixlen))
+			continue;
+		strbuf_setlen(&buf, dirlen);
+		strbuf_addstr(&buf, e->d_name);
+		unlink(buf.buf);
+	}
+	closedir(dir);
+	strbuf_release(&buf);
+}
+
+static void remove_pack_on_signal(int signo)
+{
+	remove_temporary_files();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+/*
+ * Adds all packs hex strings to the fname list, which do not
+ * have a corresponding .keep file.
+ */
+static void get_non_kept_pack_filenames(struct string_list *fname_list)
+{
+	DIR *dir;
+	struct dirent *e;
+	char *fname;
+	size_t len;
+
+	if (!(dir = opendir(packdir)))
+		return;
+
+	while ((e = readdir(dir)) != NULL) {
+		if (suffixcmp(e->d_name, ".pack"))
+			continue;
+
+		len = strlen(e->d_name) - strlen(".pack");
+		fname = xmemdupz(e->d_name, len);
+
+		if (!file_exists(mkpath("%s/%s.keep", packdir, fname)))
+			string_list_append_nodup(fname_list, fname);
+		else
+			free(fname);
+	}
+	closedir(dir);
+}
+
+static void remove_redundant_pack(const char *path_prefix, const char *hex)
+{
+	const char *exts[] = {".pack", ".idx", ".keep"};
+	int i;
+	struct strbuf buf = STRBUF_INIT;
+	size_t plen;
+
+	strbuf_addf(&buf, "%s/%s", path_prefix, hex);
+	plen = buf.len;
+
+	for (i = 0; i < ARRAY_SIZE(exts); i++) {
+		strbuf_setlen(&buf, plen);
+		strbuf_addstr(&buf, exts[i]);
+		unlink(buf.buf);
+	}
+	strbuf_release(&buf);
+}
+
+#define ALL_INTO_ONE 1
+#define LOOSEN_UNREACHABLE 2
+
+int cmd_repack(int argc, const char **argv, const char *prefix)
+{
+	const char *exts[2] = {".pack", ".idx"};
+	struct child_process cmd;
+	struct string_list_item *item;
+	struct argv_array cmd_args = ARGV_ARRAY_INIT;
+	struct string_list names = STRING_LIST_INIT_DUP;
+	struct string_list rollback = STRING_LIST_INIT_NODUP;
+	struct string_list existing_packs = STRING_LIST_INIT_DUP;
+	struct strbuf line = STRBUF_INIT;
+	int nr_packs, ext, ret, failed;
+	FILE *out;
+
+	/* variables to be filled by option parsing */
+	int pack_everything = 0;
+	int delete_redundant = 0;
+	char *unpack_unreachable = NULL;
+	int window = 0, window_memory = 0;
+	int depth = 0;
+	int max_pack_size = 0;
+	int no_reuse_delta = 0, no_reuse_object = 0;
+	int no_update_server_info = 0;
+	int quiet = 0;
+	int local = 0;
+
+	struct option builtin_repack_options[] = {
+		OPT_BIT('a', NULL, &pack_everything,
+				N_("pack everything in a single pack"), ALL_INTO_ONE),
+		OPT_BIT('A', NULL, &pack_everything,
+				N_("same as -a, and turn unreachable objects loose"),
+				   LOOSEN_UNREACHABLE),
+		OPT_BOOL('d', NULL, &delete_redundant,
+				N_("remove redundant packs, and run git-prune-packed")),
+		OPT_BOOL('f', NULL, &no_reuse_delta,
+				N_("pass --no-reuse-delta to git-pack-objects")),
+		OPT_BOOL('F', NULL, &no_reuse_object,
+				N_("pass --no-reuse-object to git-pack-objects")),
+		OPT_BOOL('n', NULL, &no_update_server_info,
+				N_("do not run git-update-server-info")),
+		OPT__QUIET(&quiet, N_("be quiet")),
+		OPT_BOOL('l', "local", &local,
+				N_("pass --local to git-pack-objects")),
+		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
+				N_("with -A, do not loosen objects older than this")),
+		OPT_INTEGER(0, "window", &window,
+				N_("size of the window used for delta compression")),
+		OPT_INTEGER(0, "window-memory", &window_memory,
+				N_("same as the above, but limit memory size instead of entries count")),
+		OPT_INTEGER(0, "depth", &depth,
+				N_("limits the maximum delta depth")),
+		OPT_INTEGER(0, "max-pack-size", &max_pack_size,
+				N_("maximum size of each packfile")),
+		OPT_END()
+	};
+
+	git_config(repack_config, NULL);
+
+	argc = parse_options(argc, argv, prefix, builtin_repack_options,
+				git_repack_usage, 0);
+
+	packdir = mkpathdup("%s/pack", get_object_directory());
+	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
+
+	sigchain_push_common(remove_pack_on_signal);
+
+	argv_array_push(&cmd_args, "pack-objects");
+	argv_array_push(&cmd_args, "--keep-true-parents");
+	argv_array_push(&cmd_args, "--honor-pack-keep");
+	argv_array_push(&cmd_args, "--non-empty");
+	argv_array_push(&cmd_args, "--all");
+	argv_array_push(&cmd_args, "--reflog");
+	if (window)
+		argv_array_pushf(&cmd_args, "--window=%u", window);
+	if (window_memory)
+		argv_array_pushf(&cmd_args, "--window-memory=%u", window_memory);
+	if (depth)
+		argv_array_pushf(&cmd_args, "--depth=%u", depth);
+	if (max_pack_size)
+		argv_array_pushf(&cmd_args, "--max_pack_size=%u", max_pack_size);
+	if (no_reuse_delta)
+		argv_array_pushf(&cmd_args, "--no-reuse-delta");
+	if (no_reuse_object)
+		argv_array_pushf(&cmd_args, "--no-reuse-object");
+
+	if (!pack_everything) {
+		argv_array_push(&cmd_args, "--unpacked");
+		argv_array_push(&cmd_args, "--incremental");
+	} else {
+		get_non_kept_pack_filenames(&existing_packs);
+
+		if (existing_packs.nr && delete_redundant) {
+			if (unpack_unreachable)
+				argv_array_pushf(&cmd_args,
+						"--unpack-unreachable=%s",
+						unpack_unreachable);
+			else if (pack_everything & LOOSEN_UNREACHABLE)
+				argv_array_push(&cmd_args,
+						"--unpack-unreachable");
+		}
+	}
+
+	if (local)
+		argv_array_push(&cmd_args,  "--local");
+	if (quiet)
+		argv_array_push(&cmd_args,  "--quiet");
+	if (delta_base_offset)
+		argv_array_push(&cmd_args,  "--delta-base-offset");
+
+	argv_array_push(&cmd_args, packtmp);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.argv = cmd_args.argv;
+	cmd.git_cmd = 1;
+	cmd.out = -1;
+	cmd.no_stdin = 1;
+
+	ret = start_command(&cmd);
+	if (ret)
+		return 1;
+
+	nr_packs = 0;
+	out = xfdopen(cmd.out, "r");
+	while (strbuf_getline(&line, out, '\n') != EOF) {
+		if (line.len != 40)
+			die("repack: Expecting 40 character sha1 lines only from pack-objects.");
+		string_list_append(&names, line.buf);
+		nr_packs++;
+	}
+	fclose(out);
+	ret = finish_command(&cmd);
+	if (ret)
+		return 1;
+	argv_array_clear(&cmd_args);
+
+	if (!nr_packs && !quiet)
+		printf("Nothing new to pack.\n");
+
+	/*
+	 * Ok we have prepared all new packfiles.
+	 * First see if there are packs of the same name and if so
+	 * if we can move them out of the way (this can happen if we
+	 * repacked immediately after packing fully.
+	 */
+	failed = 0;
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s%s", packdir,
+						item->string, exts[ext]);
+			if (!file_exists(fname)) {
+				free(fname);
+				continue;
+			}
+
+			fname_old = mkpath("%s/old-%s%s", packdir,
+						item->string, exts[ext]);
+			if (file_exists(fname_old))
+				if (unlink(fname_old))
+					failed = 1;
+
+			if (!failed && rename(fname, fname_old)) {
+				free(fname);
+				failed = 1;
+				break;
+			} else {
+				string_list_append(&rollback, fname);
+			}
+		}
+		if (failed)
+			break;
+	}
+	if (failed) {
+		struct string_list rollback_failure = STRING_LIST_INIT_DUP;
+		for_each_string_list_item(item, &rollback) {
+			char *fname, *fname_old;
+			fname = mkpathdup("%s/%s", packdir, item->string);
+			fname_old = mkpath("%s/old-%s", packdir, item->string);
+			if (rename(fname_old, fname))
+				string_list_append(&rollback_failure, fname);
+			free(fname);
+		}
+
+		if (rollback_failure.nr) {
+			int i;
+			fprintf(stderr,
+				"WARNING: Some packs in use have been renamed by\n"
+				"WARNING: prefixing old- to their name, in order to\n"
+				"WARNING: replace them with the new version of the\n"
+				"WARNING: file.  But the operation failed, and the\n"
+				"WARNING: attempt to rename them back to their\n"
+				"WARNING: original names also failed.\n"
+				"WARNING: Please rename them in %s manually:\n", packdir);
+			for (i = 0; i < rollback_failure.nr; i++)
+				fprintf(stderr, "WARNING:   old-%s -> %s\n",
+					rollback_failure.items[i].string,
+					rollback_failure.items[i].string);
+		}
+		exit(1);
+	}
+
+	/* Now the ones with the same name are out of the way... */
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname, *fname_old;
+			struct stat statbuffer;
+			fname = mkpathdup("%s/pack-%s%s",
+					packdir, item->string, exts[ext]);
+			fname_old = mkpathdup("%s-%s%s",
+					packtmp, item->string, exts[ext]);
+			if (!stat(fname_old, &statbuffer)) {
+				statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+				chmod(fname_old, statbuffer.st_mode);
+			}
+			if (rename(fname_old, fname))
+				exit(errno);
+			free(fname);
+			free(fname_old);
+		}
+	}
+
+	/* Remove the "old-" files */
+	for_each_string_list_item(item, &names) {
+		for (ext = 0; ext < 2; ext++) {
+			char *fname;
+			fname = mkpath("%s/old-pack-%s%s",
+					packdir,
+					item->string,
+					exts[ext]);
+			remove_path(fname);
+		}
+	}
+
+	/* End of pack replacement. */
+
+	if (delete_redundant) {
+		sort_string_list(&names);
+		for_each_string_list_item(item, &existing_packs) {
+			char *sha1;
+			size_t len = strlen(item->string);
+			if (len < 40)
+				continue;
+			sha1 = item->string + len - 40;
+			if (!string_list_has_string(&names, sha1))
+				remove_redundant_pack(packdir, item->string);
+		}
+		argv_array_push(&cmd_args, "prune-packed");
+		if (quiet)
+			argv_array_push(&cmd_args, "--quiet");
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args.argv;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+		argv_array_clear(&cmd_args);
+	}
+
+	if (!no_update_server_info) {
+		argv_array_push(&cmd_args, "update-server-info");
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.argv = cmd_args.argv;
+		cmd.git_cmd = 1;
+		run_command(&cmd);
+		argv_array_clear(&cmd_args);
+	}
+	remove_temporary_files();
+	string_list_clear(&names, 0);
+	string_list_clear(&rollback, 0);
+	string_list_clear(&existing_packs, 0);
+	strbuf_release(&line);
+
+	return 0;
+}
diff --git a/contrib/examples/git-repack.sh b/contrib/examples/git-repack.sh
new file mode 100755
index 0000000..7579331
--- /dev/null
+++ b/contrib/examples/git-repack.sh
@@ -0,0 +1,194 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+#
+
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git repack [options]
+--
+a               pack everything in a single pack
+A               same as -a, and turn unreachable objects loose
+d               remove redundant packs, and run git-prune-packed
+f               pass --no-reuse-delta to git-pack-objects
+F               pass --no-reuse-object to git-pack-objects
+n               do not run git-update-server-info
+q,quiet         be quiet
+l               pass --local to git-pack-objects
+unpack-unreachable=  with -A, do not loosen objects older than this
+ Packing constraints
+window=         size of the window used for delta compression
+window-memory=  same as the above, but limit memory size instead of entries count
+depth=          limits the maximum delta depth
+max-pack-size=  maximum size of each packfile
+"
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
+no_update_info= all_into_one= remove_redundant= unpack_unreachable=
+local= no_reuse= extra=
+while test $# != 0
+do
+	case "$1" in
+	-n)	no_update_info=t ;;
+	-a)	all_into_one=t ;;
+	-A)	all_into_one=t
+		unpack_unreachable=--unpack-unreachable ;;
+	--unpack-unreachable)
+		unpack_unreachable="--unpack-unreachable=$2"; shift ;;
+	-d)	remove_redundant=t ;;
+	-q)	GIT_QUIET=t ;;
+	-f)	no_reuse=--no-reuse-delta ;;
+	-F)	no_reuse=--no-reuse-object ;;
+	-l)	local=--local ;;
+	--max-pack-size|--window|--window-memory|--depth)
+		extra="$extra $1=$2"; shift ;;
+	--) shift; break;;
+	*)	usage ;;
+	esac
+	shift
+done
+
+case "`git config --bool repack.usedeltabaseoffset || echo true`" in
+true)
+	extra="$extra --delta-base-offset" ;;
+esac
+
+PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
+PACKTMP="$PACKDIR/.tmp-$$-pack"
+rm -f "$PACKTMP"-*
+trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
+
+# There will be more repacking strategies to come...
+case ",$all_into_one," in
+,,)
+	args='--unpacked --incremental'
+	;;
+,t,)
+	args= existing=
+	if [ -d "$PACKDIR" ]; then
+		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
+			| sed -e 's/^\.\///' -e 's/\.pack$//'`
+		do
+			if [ -e "$PACKDIR/$e.keep" ]; then
+				: keep
+			else
+				existing="$existing $e"
+			fi
+		done
+		if test -n "$existing" -a -n "$unpack_unreachable" -a \
+			-n "$remove_redundant"
+		then
+			# This may have arbitrary user arguments, so we
+			# have to protect it against whitespace splitting
+			# when it gets run as "pack-objects $args" later.
+			# Fortunately, we know it's an approxidate, so we
+			# can just use dots instead.
+			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
+		fi
+	fi
+	;;
+esac
+
+mkdir -p "$PACKDIR" || exit
+
+args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
+names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
+	exit 1
+if [ -z "$names" ]; then
+	say Nothing new to pack.
+fi
+
+# Ok we have prepared all new packfiles.
+
+# First see if there are packs of the same name and if so
+# if we can move them out of the way (this can happen if we
+# repacked immediately after packing fully.
+rollback=
+failed=
+for name in $names
+do
+	for sfx in pack idx
+	do
+		file=pack-$name.$sfx
+		test -f "$PACKDIR/$file" || continue
+		rm -f "$PACKDIR/old-$file" &&
+		mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
+			failed=t
+			break
+		}
+		rollback="$rollback $file"
+	done
+	test -z "$failed" || break
+done
+
+# If renaming failed for any of them, roll the ones we have
+# already renamed back to their original names.
+if test -n "$failed"
+then
+	rollback_failure=
+	for file in $rollback
+	do
+		mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
+		rollback_failure="$rollback_failure $file"
+	done
+	if test -n "$rollback_failure"
+	then
+		echo >&2 "WARNING: Some packs in use have been renamed by"
+		echo >&2 "WARNING: prefixing old- to their name, in order to"
+		echo >&2 "WARNING: replace them with the new version of the"
+		echo >&2 "WARNING: file.  But the operation failed, and"
+		echo >&2 "WARNING: attempt to rename them back to their"
+		echo >&2 "WARNING: original names also failed."
+		echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
+		for file in $rollback_failure
+		do
+			echo >&2 "WARNING:   old-$file -> $file"
+		done
+	fi
+	exit 1
+fi
+
+# Now the ones with the same name are out of the way...
+fullbases=
+for name in $names
+do
+	fullbases="$fullbases pack-$name"
+	chmod a-w "$PACKTMP-$name.pack"
+	chmod a-w "$PACKTMP-$name.idx"
+	mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
+	mv -f "$PACKTMP-$name.idx"  "$PACKDIR/pack-$name.idx" ||
+	exit
+done
+
+# Remove the "old-" files
+for name in $names
+do
+	rm -f "$PACKDIR/old-pack-$name.idx"
+	rm -f "$PACKDIR/old-pack-$name.pack"
+done
+
+# End of pack replacement.
+
+if test "$remove_redundant" = t
+then
+	# We know $existing are all redundant.
+	if [ -n "$existing" ]
+	then
+		( cd "$PACKDIR" &&
+		  for e in $existing
+		  do
+			case " $fullbases " in
+			*" $e "*) ;;
+			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
+			esac
+		  done
+		)
+	fi
+	git prune-packed ${GIT_QUIET:+-q}
+fi
+
+case "$no_update_info" in
+t) : ;;
+*) git update-server-info ;;
+esac
diff --git a/git-repack.sh b/git-repack.sh
deleted file mode 100755
index 7579331..0000000
--- a/git-repack.sh
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-
-OPTIONS_KEEPDASHDASH=
-OPTIONS_SPEC="\
-git repack [options]
---
-a               pack everything in a single pack
-A               same as -a, and turn unreachable objects loose
-d               remove redundant packs, and run git-prune-packed
-f               pass --no-reuse-delta to git-pack-objects
-F               pass --no-reuse-object to git-pack-objects
-n               do not run git-update-server-info
-q,quiet         be quiet
-l               pass --local to git-pack-objects
-unpack-unreachable=  with -A, do not loosen objects older than this
- Packing constraints
-window=         size of the window used for delta compression
-window-memory=  same as the above, but limit memory size instead of entries count
-depth=          limits the maximum delta depth
-max-pack-size=  maximum size of each packfile
-"
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-no_update_info= all_into_one= remove_redundant= unpack_unreachable=
-local= no_reuse= extra=
-while test $# != 0
-do
-	case "$1" in
-	-n)	no_update_info=t ;;
-	-a)	all_into_one=t ;;
-	-A)	all_into_one=t
-		unpack_unreachable=--unpack-unreachable ;;
-	--unpack-unreachable)
-		unpack_unreachable="--unpack-unreachable=$2"; shift ;;
-	-d)	remove_redundant=t ;;
-	-q)	GIT_QUIET=t ;;
-	-f)	no_reuse=--no-reuse-delta ;;
-	-F)	no_reuse=--no-reuse-object ;;
-	-l)	local=--local ;;
-	--max-pack-size|--window|--window-memory|--depth)
-		extra="$extra $1=$2"; shift ;;
-	--) shift; break;;
-	*)	usage ;;
-	esac
-	shift
-done
-
-case "`git config --bool repack.usedeltabaseoffset || echo true`" in
-true)
-	extra="$extra --delta-base-offset" ;;
-esac
-
-PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
-PACKTMP="$PACKDIR/.tmp-$$-pack"
-rm -f "$PACKTMP"-*
-trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
-
-# There will be more repacking strategies to come...
-case ",$all_into_one," in
-,,)
-	args='--unpacked --incremental'
-	;;
-,t,)
-	args= existing=
-	if [ -d "$PACKDIR" ]; then
-		for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
-			| sed -e 's/^\.\///' -e 's/\.pack$//'`
-		do
-			if [ -e "$PACKDIR/$e.keep" ]; then
-				: keep
-			else
-				existing="$existing $e"
-			fi
-		done
-		if test -n "$existing" -a -n "$unpack_unreachable" -a \
-			-n "$remove_redundant"
-		then
-			# This may have arbitrary user arguments, so we
-			# have to protect it against whitespace splitting
-			# when it gets run as "pack-objects $args" later.
-			# Fortunately, we know it's an approxidate, so we
-			# can just use dots instead.
-			args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
-		fi
-	fi
-	;;
-esac
-
-mkdir -p "$PACKDIR" || exit
-
-args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
-names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
-	exit 1
-if [ -z "$names" ]; then
-	say Nothing new to pack.
-fi
-
-# Ok we have prepared all new packfiles.
-
-# First see if there are packs of the same name and if so
-# if we can move them out of the way (this can happen if we
-# repacked immediately after packing fully.
-rollback=
-failed=
-for name in $names
-do
-	for sfx in pack idx
-	do
-		file=pack-$name.$sfx
-		test -f "$PACKDIR/$file" || continue
-		rm -f "$PACKDIR/old-$file" &&
-		mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
-			failed=t
-			break
-		}
-		rollback="$rollback $file"
-	done
-	test -z "$failed" || break
-done
-
-# If renaming failed for any of them, roll the ones we have
-# already renamed back to their original names.
-if test -n "$failed"
-then
-	rollback_failure=
-	for file in $rollback
-	do
-		mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
-		rollback_failure="$rollback_failure $file"
-	done
-	if test -n "$rollback_failure"
-	then
-		echo >&2 "WARNING: Some packs in use have been renamed by"
-		echo >&2 "WARNING: prefixing old- to their name, in order to"
-		echo >&2 "WARNING: replace them with the new version of the"
-		echo >&2 "WARNING: file.  But the operation failed, and"
-		echo >&2 "WARNING: attempt to rename them back to their"
-		echo >&2 "WARNING: original names also failed."
-		echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
-		for file in $rollback_failure
-		do
-			echo >&2 "WARNING:   old-$file -> $file"
-		done
-	fi
-	exit 1
-fi
-
-# Now the ones with the same name are out of the way...
-fullbases=
-for name in $names
-do
-	fullbases="$fullbases pack-$name"
-	chmod a-w "$PACKTMP-$name.pack"
-	chmod a-w "$PACKTMP-$name.idx"
-	mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
-	mv -f "$PACKTMP-$name.idx"  "$PACKDIR/pack-$name.idx" ||
-	exit
-done
-
-# Remove the "old-" files
-for name in $names
-do
-	rm -f "$PACKDIR/old-pack-$name.idx"
-	rm -f "$PACKDIR/old-pack-$name.pack"
-done
-
-# End of pack replacement.
-
-if test "$remove_redundant" = t
-then
-	# We know $existing are all redundant.
-	if [ -n "$existing" ]
-	then
-		( cd "$PACKDIR" &&
-		  for e in $existing
-		  do
-			case " $fullbases " in
-			*" $e "*) ;;
-			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
-			esac
-		  done
-		)
-	fi
-	git prune-packed ${GIT_QUIET:+-q}
-fi
-
-case "$no_update_info" in
-t) : ;;
-*) git update-server-info ;;
-esac
diff --git a/git.c b/git.c
index 2025f77..03510be 100644
--- a/git.c
+++ b/git.c
@@ -396,6 +396,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "remote", cmd_remote, RUN_SETUP },
 		{ "remote-ext", cmd_remote_ext },
 		{ "remote-fd", cmd_remote_fd },
+		{ "repack", cmd_repack, RUN_SETUP },
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-- 
1.8.4.273.ga194ead

^ permalink raw reply related	[relevance 2%]

* [PATCH 1/2] refs: remove unused function invalidate_ref_cache
@ 2013-10-26 17:03 12% Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-10-26 17:03 UTC (permalink / raw)
  To: git, gitster; +Cc: Stefan Beller

The function 'invalidate_ref_cache' was introduced in 79c7ca5 (2011-10-17,
invalidate_ref_cache(): rename function from invalidate_cached_refs())
by a rename and elevated to be publicly usable in 8be8bde (2011-10-17,
invalidate_ref_cache(): expose this function in the refs API)

However it is not used anymore, as 8bf90dc (2011-10-17, write_ref_sha1():
only invalidate the loose ref cache) and (much) later 506a760 (2013-04-22,
refs: change how packed refs are deleted) removed any calls to this
function. So it seems as if we don't need that function any more,
good bye!

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 refs.c | 7 -------
 refs.h | 8 --------
 2 files changed, 15 deletions(-)

diff --git a/refs.c b/refs.c
index 3710748..f9c1957 100644
--- a/refs.c
+++ b/refs.c
@@ -947,13 +947,6 @@ static struct ref_cache *get_ref_cache(const char *submodule)
 	return refs;
 }
 
-void invalidate_ref_cache(const char *submodule)
-{
-	struct ref_cache *refs = get_ref_cache(submodule);
-	clear_packed_ref_cache(refs);
-	clear_loose_ref_cache(refs);
-}
-
 /* The length of a peeled reference line in packed-refs, including EOL: */
 #define PEELED_LINE_LENGTH 42
 
diff --git a/refs.h b/refs.h
index b113377..87a1a79 100644
--- a/refs.h
+++ b/refs.h
@@ -165,14 +165,6 @@ extern void unlock_ref(struct ref_lock *lock);
 /** Writes sha1 into the ref specified by the lock. **/
 extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, const char *msg);
 
-/*
- * Invalidate the reference cache for the specified submodule.  Use
- * submodule=NULL to invalidate the cache for the main module.  This
- * function must be called if references are changed via a mechanism
- * other than the refs API.
- */
-extern void invalidate_ref_cache(const char *submodule);
-
 /** Setup reflog before using. **/
 int log_ref_setup(const char *ref_name, char *logfile, int bufsize);
 
-- 
1.8.4.1.605.g23c6912

^ permalink raw reply related	[relevance 12%]

* [PATCH] Documentation: add a script to generate a (long/short) options overview
  @ 2013-10-31 23:04  5% ` Stefan Beller
  2013-10-31 23:09  7%   ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2013-10-31 23:04 UTC (permalink / raw)
  To: tr, mhagger, git; +Cc: Stefan Beller

Recently a discussion started on the mailing list, which short option
shall be best for a long option. (-f being always --force and therefore
should not be reassigned another meaning in one particular command)
See http://www.mail-archive.com/git@vger.kernel.org/msg38456.html

For discussions as these we need a script to easily generate an
overview of all available one letter options, and their long option
equivalents.

As the list of options was not retrieved fully automated,
there might be minor errors or missing items.

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Documentation/generateShortOptions.py | 460 ++++++++++++++++++++++++++++++++++
 1 file changed, 460 insertions(+)
 create mode 100644 Documentation/generateShortOptions.py

diff --git a/Documentation/generateShortOptions.py b/Documentation/generateShortOptions.py
new file mode 100644
index 0000000..1d326f9
--- /dev/null
+++ b/Documentation/generateShortOptions.py
@@ -0,0 +1,460 @@
+#!/usr/bin/python
+# This script generates a table, which should help you getting a
+# better overview of the existing long and short options of the
+# various git commands. This script actually is only suited for
+# generating the table itself, as the collection of the options of
+# the git commands needs to be done manually.
+# For the majority of commands, which are written in C, a small patch
+# such as the following helps to extract the relevant cases for this
+# script. However you still need to go through the shell commands
+# manually.
+# diff --git a/parse-options.c b/parse-options.c
+# index 62e9b1c..b356ca9 100644
+# --- a/parse-options.c
+# +++ b/parse-options.c
+# @@ -500,6 +500,12 @@ int parse_options(int argc, const char **argv, const char *prefix,
+#  {
+#  	struct parse_opt_ctx_t ctx;
+#
+# +	for (; options->type != OPTION_END; options++) {
+# +		if (options->long_name && options->short_name)
+# +			printf("%s,  %c, %s\n", argv[0], options->short_name, options->long_name);
+# +	}
+# +	exit(1);
+# +
+#  	parse_options_start(&ctx, argc, argv, prefix, options, flags);
+#  	switch (parse_options_step(&ctx, options, usagestr)) {
+#  	case PARSE_OPT_HELP:
+# --
+
+
+# Command, short option, long option
+cmd_results="""add,  n, dry-run
+add,  v, verbose
+add,  i, interactive
+add,  p, patch
+add,  e, edit
+add,  f, force
+add,  u, update
+add,  N, intent-to-add
+add,  A, all
+
+am, i, interactive
+am, 3, 3way
+am, q, quiet
+am, s, signoff
+am, u, utf8
+am, k, keep
+
+annotate, p, porcelain
+
+apply,  3, 3way
+apply,  R, reverse
+apply,  v, verbose
+
+archive,  o, output
+
+blame, p, porcelain
+blame, f, show-name
+blame, n, show-number
+blame, e, show-email
+
+branch,  v, verbose
+branch,  q, quiet
+branch,  t, track
+branch,  u, set-upstream-to
+branch,  r, remotes
+branch,  a, all
+branch,  d, delete
+branch,  m, move
+branch,  l, create-reflog
+branch,  f, force
+
+check-attr,  a, all
+
+check-ignore,  q, quiet
+check-ignore,  v, verbose
+check-ignore,  n, non-matching
+
+checkout,  q, quiet
+checkout,  t, track
+checkout,  2, ours
+checkout,  3, theirs
+checkout,  f, force
+checkout,  m, merge
+checkout,  p, patch
+
+checkout-index,  a, all
+checkout-index,  f, force
+checkout-index,  q, quiet
+checkout-index,  n, no-create
+checkout-index,  u, index
+
+cherry,  v, verbose
+
+cherry-pick,  n, no-commit
+cherry-pick,  e, edit
+cherry-pick,  s, signoff
+cherry-pick,  m, mainline
+cherry-pick,  X, strategy-option
+
+clean,  q, quiet
+clean,  n, dry-run
+clean,  f, force
+clean,  i, interactive
+clean,  e, exclude
+
+clone,  v, verbose
+clone,  q, quiet
+clone,  n, no-checkout
+clone,  l, local
+clone,  s, shared
+clone,  o, origin
+clone,  b, branch
+clone,  u, upload-pack
+clone,  c, config
+
+commit,  q, quiet
+commit,  v, verbose
+commit,  F, file
+commit,  m, message
+commit,  c, reedit-message
+commit,  C, reuse-message
+commit,  s, signoff
+commit,  t, template
+commit,  e, edit
+commit,  S, gpg-sign
+commit,  a, all
+commit,  i, include
+commit,  p, patch
+commit,  o, only
+commit,  n, no-verify
+commit,  z, null
+commit,  u, untracked-files
+
+config,  f, file
+config,  l, list
+config,  e, edit
+config,  z, null
+
+count-objects,  v, verbose
+count-objects,  H, human-readable
+
+diff, u, patch
+diff, p, patch
+diff, U, unified
+diff, B, break-rewrites
+diff, M, find-renames
+diff, C, find-copies
+diff, D, irreversible-delete
+diff, a, text
+diff, b, ignore-space-change
+diff, w, ignore-all-space
+diff, W, function-context
+
+diff-files, u, patch
+diff-files, p, patch
+diff-files, U, unified
+diff-files, B, break-rewrites
+diff-files, M, find-renames
+diff-files, C, find-copies
+diff-files, D, irreversible-delete
+diff-files, a, text
+diff-files, b, ignore-space-change
+diff-files, w, ignore-all-space
+diff-files, W, function-context
+diff-files, c, cc
+# diff-index and diff-tree similar, to be done
+
+fetch,  v, verbose
+fetch,  q, quiet
+fetch,  a, append
+fetch,  f, force
+fetch,  m, multiple
+fetch,  t, tags
+fetch,  p, prune
+fetch,  k, keep
+fetch,  u, update-head-ok
+
+filter-branch, f, force
+
+fmt-merge-msg,  m, message
+fmt-merge-msg,  F, file
+
+for-each-ref,  s, shell
+for-each-ref,  p, perl
+
+format-patch,  n, numbered
+format-patch,  N, no-numbered
+format-patch,  s, signoff
+format-patch,  v, reroll-count
+format-patch,  o, output-directory
+format-patch,  k, keep-subject
+format-patch,  p, no-stat
+format-patch,  q, quiet
+
+fsck,  v, verbose
+
+fsck-objects,  v, verbose
+
+gc,  q, quiet
+
+grep,  v, invert-match
+grep,  i, ignore-case
+grep,  w, word-regexp
+grep,  a, text
+grep,  E, extended-regexp
+grep,  G, basic-regexp
+grep,  F, fixed-strings
+grep,  P, perl-regexp
+grep,  n, line-number
+grep,  l, files-with-matches
+grep,  L, files-without-match
+grep,  z, null
+grep,  c, count
+grep,  C, context
+grep,  B, before-context
+grep,  A, after-context
+grep,  p, show-function
+grep,  W, function-context
+grep,  q, quiet
+grep,  O, open-files-in-pager
+
+help,  a, all
+help,  g, guides
+help,  m, man
+help,  w, web
+help,  i, info
+
+init,  q, quiet
+
+init-db,  q, quiet
+
+insta-web, l, local
+insta-web, d, httpd
+insta-web, m, module-path
+insta-web, p, port
+insta-web, b, browser
+
+log,  q, quiet
+
+ls-files,  c, cached
+ls-files,  d, deleted
+ls-files,  m, modified
+ls-files,  o, others
+ls-files,  i, ignored
+ls-files,  s, stage
+ls-files,  k, killed
+ls-files,  u, unmerged
+ls-files,  x, exclude
+ls-files,  X, exclude-from
+
+ls-tree,  l, long
+
+ls-remotes, h, heads
+ls-remotes, t, tags
+ls-remotes, u, upload-pack
+
+merge,  e, edit
+merge,  s, strategy
+merge,  X, strategy-option
+merge,  m, message
+merge,  n, no-stat
+merge,  v, verbose
+merge,  q, quiet
+merge,  S, gpg-sign
+merge,  s, strategy
+merge,  X, strategy-option
+
+merge-base,  a, all
+
+merge-file,  p, stdout
+merge-file,  q, quiet
+
+mv,  v, verbose
+mv,  n, dry-run
+mv,  f, force
+
+pack-objects,  q, quiet
+
+prune,  n, dry-run
+prune,  v, verbose
+
+prune-packed,  n, dry-run
+prune-packed,  q, quiet
+
+pull, a, append
+pull, f, force
+pull, k, keep
+pull, u, update-head-ok
+pull, n, no-stat
+pull, q, quiet
+pull, v, verbose
+pull, r, rebase
+pull,  s, strategy
+pull,  X, strategy-option
+
+push,  v, verbose
+push,  q, quiet
+push,  n, dry-run
+push,  f, force
+push,  u, set-upstream
+
+quilt-import, n, dry-run
+
+rebase, f, force-rebase
+rebase, i, interactive
+rebase, p, preserve-merges
+rebase, m, merge
+rebase, n, no-stat
+rebase, v, verbose
+rebase, r, rebase
+rebase,  s, strategy
+rebase,  X, strategy-option
+rebase, x, exec
+
+read-tree,  v, verbose
+read-tree,  n, dry-run
+
+reflog,  q, quiet
+
+rev-list, n, max-count
+rev-list, i, regexp-ignore-case
+rev-list, E, extended-regexp
+rev-list, F, fixed-strings
+rev-list, g, walk-reflogs
+
+remote,  v, verbose
+
+repack,  q, quiet
+repack,  l, local
+
+replace,  l, list
+replace,  d, delete
+replace,  f, force
+
+reset,  q, quiet
+reset,  p, patch
+
+revert,  n, no-commit
+revert,  e, edit
+revert,  s, signoff
+revert,  m, mainline
+revert,  X, strategy-option
+
+rm,  n, dry-run
+rm,  q, quiet
+rm,  f, force
+
+show,  q, quiet
+
+show-branch,  a, all
+show-branch,  r, remotes
+show-branch,  g, reflog
+
+show-ref,  d, dereference
+show-ref,  s, hash
+show-ref,  q, quiet
+
+shortlog, n, numbered
+shortlog, s, summary
+shortlog, e, email
+
+stash, p, patch
+stash, u, include-untracked
+stash, a, all
+stash, q, quiet
+
+stage,  n, dry-run
+stage,  v, verbose
+stage,  i, interactive
+stage,  p, patch
+stage,  e, edit
+stage,  f, force
+stage,  u, update
+stage,  N, intent-to-add
+stage,  A, all
+
+status,  v, verbose
+status,  s, short
+status,  b, branch
+status,  z, null
+status,  u, untracked-files
+
+stripspace, s, strip-comments
+stripspace, c, comment-lines
+
+submodule, q, quiet
+submodule, b, branch
+submodule, f, force
+submodule, n, summary-limit
+submodule, N, no-fetch
+
+symbolic-ref,  q, quiet
+symbolic-ref,  d, delete
+
+tag,  l, list
+tag,  d, delete
+tag,  v, verify
+tag,  a, annotate
+tag,  m, message
+tag,  F, file
+tag,  s, sign
+tag,  u, local-user
+tag,  f, force
+
+update-server-info,  f, force
+
+verify-pack,  v, verbose
+verify-pack,  s, stat-only
+
+verify-tag,  v, verbose
+
+whatchanged,  q, quiet"""
+
+import subprocess
+
+column_len = {}
+column_count = {}
+cmdoptions={}
+
+for line in cmd_results.split("\n"):
+	if not len(line) or line.startswith('#'):
+		continue
+	name, short, long = line.split(",")
+
+	if not short in column_len:
+		column_len[short] = len(long)
+		column_count[short] = 0
+	column_len[short] = max(column_len[short], len(long))
+	column_count[short] += 1
+
+	if not name in cmdoptions:
+		cmdoptions[name] = {}
+	cmdoptions[name][short] = long
+
+longest_cmd = 0
+for cmd in cmdoptions:
+	longest_cmd = max(longest_cmd, len(cmd))
+
+print " "*(longest_cmd-len("Name\\short")), "Name\\short",
+
+# let's sort the columns in a way, we can see most of the options on the left hand side
+columns = []
+for key, value in sorted(column_count.iteritems(), key=lambda (k,v): (-v,k)):
+	columns += [key]
+
+# print head line
+for short in columns:
+	print "|" + " "*(1+column_len[short]-len(short)) + short,
+print
+
+# print line for each command
+for cmd in sorted(cmdoptions):
+	print " "*(longest_cmd-len(cmd)), cmd,
+	for short in columns:
+		s = ""
+		if short in cmdoptions[cmd]:
+			s = cmdoptions[cmd][short]
+		print "|" + " "*(1+column_len[short]-len(s)) + s,
+	print "  ", cmd
-- 
1.8.4.1.605.g23c6912

^ permalink raw reply related	[relevance 5%]

* Re: [PATCH] Documentation: add a script to generate a (long/short) options overview
  2013-10-31 23:04  5% ` [PATCH] Documentation: add a script to generate a (long/short) options overview Stefan Beller
@ 2013-10-31 23:09  7%   ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2013-10-31 23:09 UTC (permalink / raw)
  To: Stefan Beller, tr, mhagger, git

On 11/01/2013 12:04 AM, Stefan Beller wrote:
> Recently a discussion started on the mailing list, which short option
> shall be best for a long option. (-f being always --force and therefore
> should not be reassigned another meaning in one particular command)
> See http://www.mail-archive.com/git@vger.kernel.org/msg38456.html
> 
> For discussions as these we need a script to easily generate an
> overview of all available one letter options, and their long option
> equivalents.
> 
> As the list of options was not retrieved fully automated,
> there might be minor errors or missing items.
> 
> Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
> ---
>  Documentation/generateShortOptions.py | 460 ++++++++++++++++++++++++++++++++++
>  1 file changed, 460 insertions(+)
>  create mode 100644 Documentation/generateShortOptions.py
> 

When trying to send a follow-up patch with the table itself, I got:
fatal: /tmp/wHpJlnf1r5/0002-Documentation-add-table-viewing-short-long-options-f.patch: 19: patch contains a line longer than 998 characters
warning: no patches were sent

Is this an artifical limitation or something that actually makes sense?

Anyway here is the table, updated to carry more commands and sorted:

>From 7d2ba0af3500f1629783dfc80aafe218dee8618c Mon Sep 17 00:00:00 2001
From: Stefan Beller <stefanbeller@googlemail.com>
Date: Fri, 1 Nov 2013 00:01:21 +0100
Subject: [PATCH 2/2] Documentation: add table viewing (short/long) options for
 all commands

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Documentation/ShortOptions.txt | 73 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 Documentation/ShortOptions.txt

diff --git a/Documentation/ShortOptions.txt b/Documentation/ShortOptions.txt
new file mode 100644
index 0000000..dd76512
--- /dev/null
+++ b/Documentation/ShortOptions.txt
@@ -0,0 +1,73 @@
+         Name\short |      q |             v |             n |          s |      f |         m |                u |         a |              p |        e |                   l |                X |            i |              n |                p |            d |                  u |                 o |             f |              F |               c |         t |     z |       a |                    b |      q |              A |              N |             k |                   i |               s |       3 |              C |         S |       b |       g |        r |            w |               B |            C |                    D |             M |        U |                 W |              c |           e |     k |            m |       r |        v |                 w |     2 |  
              B |                E |             G |               H |                    L |                    O |            P |        R |                 W |        x |     3 |                E |
              F |         N |      d |             g |      h |      l |     t |     x
+                add |        |       verbose |       dry-run |            |  force |           |           update |           |          patch |     edit |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |            all |  intent-to-add |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          add
+                 am |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |               utf8 |                   |               |                |                 |           |       |         |                      |  quiet |                |                |               |         interactive |         signoff |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |  keep |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |  3way |                  |
                |           |        |               |        |        |       |          am
+           annotate |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |        porcelain |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          annotate
+              apply |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |    3way |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |  reverse |                   |          |       |                  |
                |           |        |               |        |        |       |          apply
+            archive |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |            output |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          archive
+              blame |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |    show-number |        porcelain |              |                    |                   |     show-name |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |  show-email |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          blame
+             branch |  quiet |       verbose |               |            |  force |      move |  set-upstream-to |       all |                |          |       create-reflog |                  |              |                |                  |       delete |                    |                   |               |                |                 |     track |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |  remotes |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          branch
+         check-attr |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          check-attr
+       check-ignore |  quiet |       verbose |  non-matching |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          check-ignore
+           checkout |  quiet |               |               |            |  force |     merge |                  |           |          patch |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |     track |       |         |                      |        |                |                |               |                     |                 |  theirs |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |  ours |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          checkout
+     checkout-index |  quiet |               |     no-create |            |  force |           |            index |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          checkout-index
+             cherry |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          cherry
+        cherry-pick |        |               |     no-commit |    signoff |        |  mainline |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          cherry-pick
+              clean |  quiet |               |       dry-run |            |  force |           |                  |           |                |  exclude |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          clean
+              clone |  quiet |       verbose |   no-checkout |     shared |        |           |      upload-pack |           |                |          |               local |                  |              |                |                  |              |                    |            origin |               |                |          config |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |  branch |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          clone
+             commit |  quiet |       verbose |     no-verify |    signoff |        |   message |  untracked-files |       all |          patch |     edit |                     |                  |      include |                |                  |              |                    |              only |               |           file |  reedit-message |  template |  null |         |                      |        |                |                |               |                     |                 |         |  reuse-message |  gpg-sign |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          commit
+             config |        |               |               |            |   file |           |                  |           |                |     edit |                list |                  |              |                |                  |              |                    |                   |               |                |                 |           |  null |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          config
+      count-objects |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |  human-readable |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          count-objects
+               diff |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |              patch |                   |               |                |                 |           |       |    text |  ignore-space-change |        |                |                |               |                     |                 |         |                |           |         |         |          |              |  break-rewrites |  find-copies |  irreversible-delete |  find-renames |  unified |  function-context |                |             |       |              |         |          |  ignore-all-space |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          diff
+         diff-files |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |              patch |                   |               |                |                 |           |       |    text |  ignore-space-change |        |                |                |               |                     |                 |         |                |           |         |         |          |              |  break-rewrites |  find-copies |  irreversible-delete |  find-renames |  unified |  function-context |             cc |             |       |              |         |          |  ignore-all-space |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          diff-files
+              fetch |  quiet |       verbose |               |            |  force |  multiple |   update-head-ok |    append |          prune |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |      tags |       |         |                      |        |                |                |          keep |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          fetch
+      filter-branch |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |         force |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          filter-branch
+      fmt-merge-msg |        |               |               |            |        |   message |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |           file |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          fmt-merge-msg
+       for-each-ref |        |               |               |      shell |        |           |                  |           |           perl |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          for-each-ref
+       format-patch |  quiet |  reroll-count |      numbered |    signoff |        |           |                  |           |        no-stat |          |                     |                  |              |                |                  |              |                    |  output-directory |               |                |                 |           |       |         |                      |        |                |    no-numbered |  keep-subject |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          format-patch
+               fsck |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          fsck
+       fsck-objects |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          fsck-objects
+                 gc |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          gc
+               grep |  quiet |  invert-match |   line-number |            |        |           |                  |      text |  show-function |          |  files-with-matches |                  |  ignore-case |                |                  |              |                    |                   |               |  fixed-strings |           count |           |  null |         |                      |        |  after-context |                |               |                     |                 |         |        context |           |         |         |          |  word-regexp |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
 before-context |  extended-regexp |  basic-regexp |                 |  files-without-match |  open-files-in-pager |  perl-regexp |          |  function-context |          |       |                  |
                |           |        |               |        |        |       |          grep
+               help |        |               |               |            |        |       man |                  |       all |                |          |                     |                  |         info |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |  guides |          |          web |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          help
+               init |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          init
+            init-db |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          init-db
+          insta-web |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |             port |              |                    |                   |               |                |                 |           |       |         |              browser |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |  module-path |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |  httpd |               |        |  local |       |          insta-web
+                log |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          log
+           ls-files |        |               |               |      stage |        |  modified |         unmerged |           |                |          |                     |     exclude-from |      ignored |                |                  |      deleted |                    |            others |               |                |          cached |           |       |         |                      |        |                |                |        killed |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |  exclude |       |                  |
                |           |        |               |        |        |       |          ls-files
+         ls-remotes |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |        upload-pack |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |  heads |        |  tags |          ls-remotes
+            ls-tree |        |               |               |            |        |           |                  |           |                |          |                long |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          ls-tree
+              merge |  quiet |       verbose |       no-stat |   strategy |        |   message |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |  gpg-sign |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          merge
+         merge-base |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          merge-base
+         merge-file |  quiet |               |               |            |        |           |                  |           |         stdout |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          merge-file
+                 mv |        |       verbose |       dry-run |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          mv
+       pack-objects |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          pack-objects
+              prune |        |       verbose |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          prune
+       prune-packed |  quiet |               |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          prune-packed
+               pull |        |               |               |   strategy |        |           |                  |           |                |          |                     |  strategy-option |              |        no-stat |                  |              |     update-head-ok |                   |         force |                |                 |           |       |  append |                      |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |  keep |              |  rebase |  verbose |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          pull
+               push |  quiet |       verbose |       dry-run |            |  force |           |     set-upstream |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          push
+       quilt-import |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |        dry-run |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          quilt-import
+          read-tree |        |       verbose |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          read-tree
+             rebase |        |               |               |   strategy |        |           |                  |           |                |          |                     |  strategy-option |              |        no-stat |  preserve-merges |              |                    |                   |  force-rebase |                |                 |           |       |         |                      |        |                |                |               |         interactive |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |        merge |  rebase |  verbose |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |  exec    rebase
+             reflog |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          reflog
+             remote |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          remote
+             repack |  quiet |               |               |            |        |           |                  |           |                |          |               local |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          repack
+            replace |        |               |               |            |  force |           |                  |           |                |          |                list |                  |              |                |                  |       delete |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          replace
+              reset |  quiet |               |               |            |        |           |                  |           |          patch |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          reset
+           rev-list |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |      max-count |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |  regexp-ignore-case |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |  extended-regexp |
  fixed-strings |           |        |  walk-reflogs |        |        |       |          rev-list
+             revert |        |               |     no-commit |    signoff |        |  mainline |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          revert
+                 rm |  quiet |               |       dry-run |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          rm
+           shortlog |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |       numbered |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |         summary |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |       email |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          shortlog
+               show |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          show
+        show-branch |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |  reflog |  remotes |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          show-branch
+           show-ref |  quiet |               |               |       hash |        |           |                  |           |                |          |                     |                  |              |                |                  |  dereference |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          show-ref
+              stage |        |       verbose |       dry-run |            |  force |           |           update |           |          patch |     edit |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |            all |  intent-to-add |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          stage
+              stash |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |  include-untracked |                   |               |                |                 |           |       |     all |                      |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          stash
+             status |        |       verbose |               |      short |        |           |  untracked-files |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |  null |         |                      |        |                |                |               |                     |                 |         |                |           |  branch |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          status
+         stripspace |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |  strip-comments |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |  comment-lines |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          stripspace
+          submodule |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |  summary-limit |                  |              |                    |                   |         force |                |                 |           |       |         |               branch |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |  no-fetch |        |               |        |        |       |          submodule
+       symbolic-ref |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |       delete |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          symbolic-ref
+                tag |        |        verify |               |       sign |  force |   message |       local-user |  annotate |                |          |                list |                  |              |                |                  |       delete |                    |                   |               |           file |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          tag
+ update-server-info |        |               |               |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          update-server-info
+        verify-pack |        |       verbose |               |  stat-only |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          verify-pack
+         verify-tag |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          verify-tag
+        whatchanged |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          whatchanged
-- 
1.8.4.1.605.g23c6912

^ permalink raw reply related	[relevance 7%]

* [ANNOUNCE] Git v1.8.5-rc1
@ 2013-11-06 23:57  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2013-11-06 23:57 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate Git v1.8.5-rc1 is now available for testing
at the usual places.

The release tarballs are found at:

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

and their SHA-1 checksums are:

005ed6e0e91043d1d9da9a47f0235fdac240269a  git-1.8.5.rc1.tar.gz
542586fc562acb88aec807cd27ae0dc0d4d507f7  git-htmldocs-1.8.5.rc1.tar.gz
5d7f057c9b5bc4d1b610ce18b986b28320751774  git-manpages-1.8.5.rc1.tar.gz

The following public repositories all have a copy of the v1.8.5-rc1
tag and the master branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v1.8.5 Release Notes (draft)
========================

Backward compatibility notes (for Git 2.0)
------------------------------------------

When "git push [$there]" does not say what to push, we have used the
traditional "matching" semantics so far (all your branches were sent
to the remote as long as there already are branches of the same name
over there).  In Git 2.0, the default will change to the "simple"
semantics that pushes:

 - only the current branch to the branch with the same name, and only
   when the current branch is set to integrate with that remote
   branch, if you are pushing to the same remote as you fetch from; or

 - only the current branch to the branch with the same name, if you
   are pushing to a remote that is not where you usually fetch from.

Use the user preference configuration variable "push.default" to
change this.  If you are an old-timer who is used to the "matching"
semantics, you can set the variable to "matching" to keep the
traditional behaviour.  If you want to live in the future early, you
can set it to "simple" today without waiting for Git 2.0.

When "git add -u" (and "git add -A") is run inside a subdirectory and
does not specify which paths to add on the command line, it
will operate on the entire tree in Git 2.0 for consistency
with "git commit -a" and other commands.  There will be no
mechanism to make plain "git add -u" behave like "git add -u .".
Current users of "git add -u" (without a pathspec) should start
training their fingers to explicitly say "git add -u ."
before Git 2.0 comes.  A warning is issued when these commands are
run without a pathspec and when you have local changes outside the
current directory, because the behaviour in Git 2.0 will be different
from today's version in such a situation.

In Git 2.0, "git add <path>" will behave as "git add -A <path>", so
that "git add dir/" will notice paths you removed from the directory
and record the removal.  Versions before Git 2.0, including this
release, will keep ignoring removals, but the users who rely on this
behaviour are encouraged to start using "git add --ignore-removal <path>"
now before 2.0 is released.

The default prefix for "git svn" will change in Git 2.0.  For a long
time, "git svn" created its remote-tracking branches directly under
refs/remotes, but it will place them under refs/remotes/origin/ unless
it is told otherwise with its --prefix option.


Updates since v1.8.4
--------------------

Foreign interfaces, subsystems and ports.

 * "git-svn" used with SVN 1.8.0 when talking over https:// connection
   dumped core due to a bug in the serf library that SVN uses.  Work
   it around on our side, even though the SVN side is being fixed.

 * On MacOS X, we detected if the filesystem needs the "pre-composed
   unicode strings" workaround, but did not automatically enable it.
   Now we do.

 * remote-hg remote helper misbehaved when interacting with a local Hg
   repository relative to the home directory, e.g. "clone hg::~/there".

 * imap-send ported to OS X uses Apple's security framework instead of
   OpenSSL one.

 * Subversion 1.8.0 that was recently released breaks older subversion
   clients coming over http/https in various ways.

 * "git fast-import" treats an empty path given to "ls" as the root of
   the tree.


UI, Workflows & Features

 * xdg-open can be used as a browser backend for "git web-browse"
   (hence to show "git help -w" output), when available.

 * "git grep" and "git show" pays attention to "--textconv" option
   when these commands are told to operate on blob objects (e.g. "git
   grep -e pattern HEAD:Makefile").

 * "git replace" helper no longer allows an object to be replaced with
   another object of a different type to avoid confusion (you can
   still manually craft such replacement using "git update-ref", as an
   escape hatch).

 * "git status" no longer prints dirty status information for
   submodules for which submodule.$name.ignore is set to "all".

 * "git rebase -i" honours core.abbrev when preparing the insn sheet
   for editing.

 * "git status" during a cherry-pick shows what original commit is
   being picked.

 * Instead of typing four capital letters "HEAD", you can say "@" now,
   e.g. "git log @".

 * "git check-ignore" follows the same rule as "git add" and "git
   status" in that the ignore/exclude mechanism does not take effect
   on paths that are already tracked.  With "--no-index" option, it
   can be used to diagnose which paths that should have been ignored
   have been mistakenly added to the index.

 * Some irrelevant "advice" messages that are shared with "git status"
   output have been removed from the commit log template.

 * "update-refs" learnt a "--stdin" option to read multiple update
   requests and perform them in an all-or-none fashion.

 * Just like "make -C <directory>", "git -C <directory> ..." tells Git
   to go there before doing anything else.

 * Just like "git checkout -" knows to check out and "git merge -"
   knows to merge the branch you were previously on, "git cherry-pick"
   now understands "git cherry-pick -" to pick from the previous
   branch.

 * "git status" now omits the prefix to make its output a comment in a
   commit log editor, which is not necessary for human consumption.
   Scripts that parse the output of "git status" are advised to use
   "git status --porcelain" instead, as its format is stable and easier
   to parse.

 * Make "foo^{tag}" to peel a tag to itself, i.e. no-op., and fail if
   "foo" is not a tag.  "git rev-parse --verify v1.0^{tag}" would be
   a more convenient way to say "test $(git cat-file -t v1.0) = tag".

 * "git branch -v -v" (and "git status") did not distinguish among a
   branch that does not build on any other branch, a branch that is in
   sync with the branch it builds on, and a branch that is configured
   to build on some other branch that no longer exists.

 * Earlier we started rejecting an attempt to add 0{40} object name to
   the index and to tree objects, but it sometimes is necessary to
   allow so to be able to use tools like filter-branch to correct such
   broken tree objects.  "filter-branch" can again be used to to do
   so.

 * "git config" did not provide a way to set or access numbers larger
   than a native "int" on the platform; it now provides 64-bit signed
   integers on all platforms.

 * "git pull --rebase" always chose to do the bog-standard flattening
   rebase.  You can tell it to run "rebase --preserve-merges" by
   setting "pull.rebase" configuration to "preserve".

 * "git push --no-thin" actually disables the "thin pack transfer"
   optimization.

 * Magic pathspecs like ":(icase)makefile" that matches both Makefile
   and makefile and ":(glob)foo/**/bar" that matches "bar" in "foo"
   and any subdirectory of "foo" can be used in more places.

 * The "http.*" variables can now be specified per URL that the
   configuration applies.  For example,

   [http]
       sslVerify = true
   [http "https://weak.example.com/"]
       sslVerify = false

   would flip http.sslVerify off only when talking to that specified
   site.

 * "git mv A B" when moving a submodule A has been taught to
   relocate its working tree and to adjust the paths in the
   .gitmodules file.

 * "git blame" can now take more than one -L option to discover the
   origin of multiple blocks of the lines.

 * The http transport clients can optionally ask to save cookies
   with http.savecookies configuration variable.

 * "git push" learned a more fine grained control over a blunt
   "--force" when requesting a non-fast-forward update with the
   "--force-with-lease=<refname>:<expected object name>" option.

 * "git diff --diff-filter=<classes of changes>" can now take
   lowercase letters (e.g. "--diff-filter=d") to mean "show
   everything but these classes".  "git diff-files -q" is now a
   deprecated synonym for "git diff-files --diff-filter=d".

 * "git fetch" (hence "git pull" as well) learned to check
   "fetch.prune" and "remote.*.prune" configuration variables and
   to behave as if the "--prune" command line option was given.

 * "git check-ignore -z" applied the NUL termination to both its input
   (with --stdin) and its output, but "git check-attr -z" ignored the
   option on the output side. Make both honor -z on the input and
   output side the same way.

 * "git whatchanged" may still be used by old timers, but mention of
   it in documents meant for new users will only waste readers' time
   wonderig what the difference is between it and "git log".  Make it
   less prominent in the general part of the documentation and explain
   that it is merely a "git log" with different default behaviour in
   its own document.


Performance, Internal Implementation, etc.

 * "git for-each-ref" when asking for merely the object name does not
   have to parse the object pointed at by the refs; the codepath has
   been optimized.

 * The HTTP transport will try to use TCP keepalive when able.

 * "git repack" is now written in C.

 * Build procedure for MSVC has been updated.

 * If a build-time fallback is set to "cat" instead of "less", we
   should apply the same "no subprocess or pipe" optimization as we
   apply to user-supplied GIT_PAGER=cat.

 * Many commands use --dashed-option as a operation mode selector
   (e.g. "git tag --delete") that the user can use at most one
   (e.g. "git tag --delete --verify" is a nonsense) and you cannot
   negate (e.g. "git tag --no-delete" is a nonsense).  parse-options
   API learned a new OPT_CMDMODE macro to make it easier to implement
   such a set of options.

 * OPT_BOOLEAN() in parse-options API was misdesigned to be "counting
   up" but many subcommands expect it to behave as "on/off". Update
   them to use OPT_BOOL() which is a proper boolean.

 * "git gc" exits early without doing a double-work when it detects
   that another instance of itself is already running.

 * Under memory pressure and/or file descriptor pressure, we used to
   close pack windows that are not used and also closed filehandle to
   an open but unused packfiles. These are now controlled separately
   to better cope with the load.

Also contains various documentation updates and code clean-ups.


Fixes since v1.8.4
------------------

Unless otherwise noted, all the fixes since v1.8.4 in the maintenance
track are contained in this release (see release notes to them for
details).

 * An ancient How-To on serving Git repositories on an HTTP server
   lacked a warning that it has been mostly superseded with more
   modern way.
   (merge 6d52bc3 sc/doc-howto-dumb-http later to maint).

 * The interaction between use of Perl in our test suite and NO_PERL
   has been clarified a bit.
   (merge f8fc0ee jn/test-prereq-perl-doc later to maint).

 * The synopsis section of "git unpack-objects" documentation has been
   clarified a bit.
   (merge 61e2e22 vd/doc-unpack-objects later to maint).

 * We did not generate HTML version of documentation to "git subtree"
   in contrib/.
   (merge 95c62fb jk/subtree-install-fix later to maint).

 * A fast-import stream expresses a pathname with funny characters by
   quoting them in C style; remote-hg remote helper forgot to unquote
   such a path.
   (merge 1136265 ap/remote-hg-unquote-cquote later to maint).

 * "git reset -p HEAD" has a codepath to special case it to behave
   differently from resetting to contents of other commits, but a
   recent change broke it.

 * Coloring around octopus merges in "log --graph" output was screwy.
   (merge 339c17b hn/log-graph-color-octopus later to maint).

 * "git checkout topic", when there is not yet a local "topic" branch
   but there is a unique remote-tracking branch for a remote "topic"
   branch, pretended as if "git checkout -t -b topic remote/$r/topic"
   (for that unique remote $r) was run. This hack however was not
   implemented for "git checkout topic --".
   (merge bca3969 mm/checkout-auto-track-fix later to maint).

 * One long-standing flaw in the pack transfer protocol used by "git
   clone" was that there was no way to tell the other end which branch
   "HEAD" points at, and the receiving end needed to guess.  A new
   capability has been defined in the pack protocol to convey this
   information so that cloning from a repository with more than one
   branches pointing at the same commit where the HEAD is at now
   reliably sets the initial branch in the resulting repository.
   (merge 360a326 jc/upload-pack-send-symref later to maint).

 * We did not handle cases where http transport gets redirected during
   the authorization request (e.g. from http:// to https://).
   (merge 70900ed jk/http-auth-redirects later to maint).

 * Bash prompting code to deal with an SVN remote as an upstream
   were coded in a way not supported by older Bash versions (3.x).
   (merge 52ec889 sg/prompt-svn-remote-fix later to maint).

 * The fall-back parsing of commit objects with broken author or
   committer lines were less robust than ideal in picking up the
   timestamps.
   (merge 03818a4 jk/split-broken-ident later to maint).

 * "git rev-list --objects ^v1.0^ v1.0" gave v1.0 tag itself in the
   output, but "git rev-list --objects v1.0^..v1.0" did not.
   (merge 895c5ba jc/revision-range-unpeel later to maint).

 * "git clone" gave some progress messages to the standard output, not
   to the standard error, and did not allow suppressing them with the
   --no-progress option.
   (merge 643f918 jk/clone-progress-to-stderr later to maint).

 * "format-patch --from=<whom>" forgot to omit unnecessary in-body
   from line, i.e. when <whom> is the same as the real author.
   (merge 662cc30 jk/format-patch-from later to maint).

 * "git shortlog" used to choke and die when there is a malformed
   commit (e.g. missing authors); it now simply ignore such a commit
   and keeps going.
   (merge cd4f09e jk/shortlog-tolerate-broken-commit later to maint).

 * "git merge-recursive" did not parse its "--diff-algorithm=" command
   line option correctly.
   (merge 6562928 jk/diff-algo later to maint).

 * When running "fetch -q", a long silence while the sender side
   computes the set of objects to send can be mistaken by proxies as
   dropped connection.  The server side has been taught to send a
   small empty messages to keep the connection alive.
   (merge 115dedd jk/upload-pack-keepalive later to maint).

 * "git rebase" had a portability regression in v1.8.4 to trigger a
   bug in some BSD shell implementations.
   (merge 99855dd mm/rebase-continue-freebsd-WB later to maint).

 * "git branch --track" had a minor regression in v1.8.3.2 and later
   that made it impossible to base your local work on anything but a
   local branch of the upstream repository you are tracking from.
   (merge b0f49ff jh/checkout-auto-tracking later to maint).

 * When the webserver responds with "405 Method Not Allowed", "git
   http-backend" should tell the client what methods are allowed with
   the "Allow" header.
   (merge 9247be0 bc/http-backend-allow-405 later to maint).

 * When there is no sufficient overlap between old and new history
   during a "git fetch" into a shallow repository, objects that the
   sending side knows the receiving end has were unnecessarily sent.
   (merge f21d2a7 nd/fetch-into-shallow later to maint).

 * "git cvsserver" computed the permission mode bits incorrectly for
   executable files.
   (merge 1b48d56 jc/cvsserver-perm-bit-fix later to maint).

 * When send-email comes up with an error message to die with upon
   failure to start an SSL session, it tried to read the error string
   from a wrong place.
   (merge 6cb0c88 bc/send-email-ssl-die-message-fix later to maint).

 * The implementation of "add -i" has a crippling code to work around
   ActiveState Perl limitation but it by mistake also triggered on Git
   for Windows where MSYS perl is used.
   (merge df17e77 js/add-i-mingw later to maint).

 * We made sure that we notice the user-supplied GIT_DIR is actually a
   gitfile, but did not do the same when the default ".git" is a
   gitfile.
   (merge 487a2b7 nd/git-dir-pointing-at-gitfile later to maint).

 * When an object is not found after checking the packfiles and then
   loose object directory, read_sha1_file() re-checks the packfiles to
   prevent racing with a concurrent repacker; teach the same logic to
   has_sha1_file().
   (merge 45e8a74 jk/has-sha1-file-retry-packed later to maint).

 * "git commit --author=$name", when $name is not in the canonical
   "A. U. Thor <au.thor@example.xz>" format, looks for a matching name
   from existing history, but did not consult mailmap to grab the
   preferred author name.
   (merge ea16794 ap/commit-author-mailmap later to maint).

 * "git ls-files -k" needs to crawl only the part of the working tree
   that may overlap the paths in the index to find killed files, but
   shared code with the logic to find all the untracked files, which
   made it unnecessarily inefficient.
   (merge 680be04 jc/ls-files-killed-optim later to maint).

 * The commit object names in the insn sheet that was prepared at the
   beginning of "rebase -i" session can become ambiguous as the
   rebasing progresses and the repository gains more commits. Make
   sure the internal record is kept with full 40-hex object names.
   (merge 75c6976 es/rebase-i-no-abbrev later to maint).

 * "git rebase --preserve-merges" internally used the merge machinery
   and as a side effect, left merge summary message in the log, but
   when rebasing, there should not be a need for merge summary.
   (merge a9f739c rt/rebase-p-no-merge-summary later to maint).

 * A call to xread() was used without a loop around to cope with short
   read in the codepath to stream new contents to a pack.
   (merge e92527c js/xread-in-full later to maint).

 * "git rebase -i" forgot that the comment character can be
   configurable while reading its insn sheet.
   (merge 7bca7af es/rebase-i-respect-core-commentchar later to maint).

 * The mailmap support code read past the allocated buffer when the
   mailmap file ended with an incomplete line.
   (merge f972a16 jk/mailmap-incomplete-line later to maint).

 * We used to send a large request to read(2)/write(2) as a single
   system call, which was bad from the latency point of view when
   the operation needs to be killed, and also triggered an error on
   broken 64-bit systems that refuse to take more than 2GB read or
   write in one go.
   (merge a487916 sp/clip-read-write-to-8mb later to maint).

 * "git fetch" that auto-followed tags incorrectly reused the
   connection with Git-aware transport helper (like the sample "ext::"
   helper shipped with Git).
   (merge 0f73f8b jc/transport-do-not-use-connect-twice-in-fetch later to maint).

 * "git log --full-diff -- <pathspec>" showed a huge diff for paths
   outside the given <pathspec> for each commit, instead of showing
   the change relative to the parent of the commit.  "git reflog -p"
   had a similar problem.
   (merge 838f9a1 tr/log-full-diff-keep-true-parents later to maint).

 * Setting submodule.*.path configuration variable to true (without
   giving "= value") caused Git to segfault.
   (merge 4b05440 jl/some-submodule-config-are-not-boolean later to maint).

 * "git rebase -i" (there could be others, as the root cause is pretty
   generic) fed a random, data dependeant string to 'echo' and
   expects it to come out literally, corrupting its error message.
   (merge 89b0230 mm/no-shell-escape-in-die-message later to maint).

 * Some people still use rather old versions of bash, which cannot
   grok some constructs like 'printf -v varname' the prompt and
   completion code started to use recently.
   (merge a44aa69 bc/completion-for-bash-3.0 later to maint).

 * Code to read configuration from a blob object did not compile on
   platforms with fgetc() etc. implemented as macros.
   (merge 49d6cfa hv/config-from-blob later to maint-1.8.3).

 * The recent "short-cut clone connectivity check" topic broke a
   shallow repository when a fetch operation tries to auto-follow tags.
   (merge 6da8bdc nd/fetch-pack-shallow-fix later to maint-1.8.3).

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

Changes since v1.8.5-rc0 are as follows:

Anders Kaseorg (1):
      cvsserver: Determinize output to combat Perl 5.18 hash randomization

Antoine Pelisse (1):
      remote-hg: unquote C-style paths when exporting

Ben Walton (2):
      Change sed i\ usage to something Solaris' sed can handle
      Avoid difference in tr semantics between System V and BSD

Felipe Contreras (12):
      merge: simplify ff-only option
      t: replace pulls with merges
      revision: add missing include
      branch: trivial style fix
      sha1-name: trivial style cleanup
      transport-helper: trivial style fix
      describe: trivial style fixes
      pretty: trivial style fix
      revision: trivial style fixes
      diff: trivial style fix
      run-command: trivial style fixes
      setup: trivial style fixes

Jeff King (7):
      add-interactive: handle unborn branch in patch mode
      reset: pass real rev name to add--interactive
      howto: add article on recovering a corrupted object
      t: provide a perl() function which uses $PERL_PATH
      t: use perl instead of "$PERL_PATH" where applicable
      for-each-ref: avoid loading objects to print %(objectname)
      subtree: add makefile target for html docs

Jens Lehmann (1):
      mv: Fix spurious warning when moving a file in presence of submodules

Johannes Sixt (4):
      t5300-pack-object: do not compare binary data using test_cmp
      Windows: a test_cmp that is agnostic to random LF <> CRLF conversions
      tests: undo special treatment of CRLF for Windows
      t3200: do not open a HTML manual page when DEFAULT_MAN_FORMAT is html

Jonathan Nieder (1):
      t/README: tests can use perl even with NO_PERL

Junio C Hamano (5):
      doc/pull: clarify the illustrations
      Update draft release notes to 1.8.5
      t4015: simplify sed command that is not even seen by sed
      Update draft release notes to 1.8.5
      Git 1.8.5-rc1

Kacper Kornet (1):
      Fix '\%o' for printf from coreutils

Rüdiger Sonderfeld (1):
      web--browse: Add support for xdg-open

Sitaram Chamarty (1):
      doc/howto: warn about (dumb)http server document being too old

Stefan Beller (2):
      refs: remove unused function invalidate_ref_cache
      cache: remove unused function 'have_git_dir'

Vivien Didelot (2):
      Documentation: restore a space in unpack-objects usage
      Documentation: "pack-file" is not literal in unpack-objects

^ permalink raw reply	[relevance 2%]

* Unify subcommand structure; introduce double dashes for all subcommands?
@ 2014-07-23 13:35  4% Stefan Beller
  2014-07-23 17:52  2% ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2014-07-23 13:35 UTC (permalink / raw)
  To: GIT Mailing-list

In the user survey 2012 question 23 ("In your opinion, which areas in
Git need improvement?"),
the most crucial point identified was the user interface.
I wonder if there are any more recent surveys, showing if this has changed.
Now when we want to improve the user interface, we're likely talking
about the porcelain
commands only, as that's what most users perceive as the commandline
user interface.

A git command is generally setup as:
	git <command> [<subcommand>] [<options>] ...

The subcommands vary wildly by the nature of the command. However all
subcommands
could at least follow one style. The commands bundle, notes, stash and
submodule
have subcommands without two leading dashes (i.e. git stash list) as
opposed to all
other commands (i.e. git tag --list).

So my proposal is to unify the structure of the subcommands to either
have always
leading dashes or never. This would need a longterm thinking of course
(e.g. introduce new options with(out) dashes, but support existing
commands until git 3.0
or such, then drop them.)

Was there a discussion about this topic already?
I'd like to read on these discussions, if any.

I could think about the following points being interesting
 * user interface (what is more appealing to a user?)
 * ease of transition (Is it really worth it? How long does it take to
pay off?)
 * ease of implementation (Could we reuse the option parser already in
   place for the double-dashed subcommands, i.e. have less LoC)
 * error-proneness of the transition

Thanks,
Stefan

^ permalink raw reply	[relevance 4%]

* Re: Unify subcommand structure; introduce double dashes for all subcommands?
  2014-07-23 13:35  4% Unify subcommand structure; introduce double dashes for all subcommands? Stefan Beller
@ 2014-07-23 17:52  2% ` Junio C Hamano
  2014-08-10 15:26  2%   ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2014-07-23 17:52 UTC (permalink / raw)
  To: Stefan Beller; +Cc: GIT Mailing-list

Stefan Beller <stefanbeller@gmail.com> writes:

> A git command is generally setup as:
> 	git <command> [<subcommand>] [<options>] ...
>
> The subcommands vary wildly by the nature of the command. However all
> subcommands
> could at least follow one style. The commands bundle, notes, stash and
> submodule
> have subcommands without two leading dashes (i.e. git stash list) as
> opposed to all
> other commands (i.e. git tag --list).

Sounds familiar.  E.g. here is a similar thread about a year ago.

  http://thread.gmane.org/gmane.comp.version-control.git/231376/focus=231478

Further discussions to make the plan more concrete is very much
welcomed.

Thanks.

^ permalink raw reply	[relevance 2%]

* [ANNOUNCE] Git v2.1.0-rc0
@ 2014-07-27 23:18  3% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-07-27 23:18 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

An early preview release Git v2.1.0-rc0 is now available for testing
at the usual places.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/testing/

The following public repositories all have a copy of the 'v2.1.0-rc0'
tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v2.1 Release Notes (draft)
==============================

Backward compatibility notes
----------------------------

 * The default value we give to the environment variable LESS has been
   changed from "FRSX" to "FRX", losing "S" (chop long lines instead
   of wrapping).  Existing users who prefer not to see line-wrapped
   output may want to set

     $ git config core.pager "less -S"

   to restore the traditional behaviour.  It is expected that people
   find output from the most subcommands easier to read with the new
   default, except for "blame" which tends to produce really long
   lines.  To override the new default only for "git blame", you can
   do this:

     $ git config pager.blame "less -S"

 * A few disused directories in contrib/ have been retired.


Updates since v2.0
------------------

UI, Workflows & Features

 * Since the very beginning of Git, we gave the LESS environment a
   default value "FRSX" when we spawn "less" as the pager.  "S" (chop
   long lines instead of wrapping) has been removed from this default
   set of options, because it is more or less a personal taste thing,
   as opposed to others that have good justifications (i.e. "R" is
   very much justified because many kinds of output we produce are
   colored and "FX" is justified because output we produce is often
   shorter than a page).

 * The logic and data used to compute the display width needed for
   UTF-8 strings have been updated to match Unicode 7.0 better.

 * HTTP-based transports learned to propagate the error messages from
   the webserver better to the client coming over the HTTP transport.

 * The completion script for bash (in contrib/) has been updated to
   handle aliases that define complex sequence of commands better.

 * The "core.preloadindex" configuration variable is by default
   enabled, allowing modern platforms to take advantage of the
   multiple cores they have.

 * "git clone" applies the "if cloning from a local disk, physically
   copy repository using hardlinks, unless otherwise told not to with
   --no-local" optimization when url.*.insteadOf mechanism rewrites a
   "git clone $URL" that refers to a repository over the network to a
   clone from a local disk.

 * "git commit --date=<date>" option learned to read from more
   timestamp formats, including "--date=now".

 * The `core.commentChar` configuration variable is used to specify a
   custom comment character other than the default "#" to be used in
   the commit log editor.  This can be set to `auto` to attempt to
   choose a different character that does not conflict with what
   already starts a line in the message being edited for cases like
   "git commit --amend".

 * "git format-patch" learned --signature-file=<file> to take the mail
   signature from.

 * "git grep" learned grep.fullname configuration variable to force
   "--full-name" to be default.  This may cause regressions on
   scripted users that do not expect this new behaviour.

 * "git imap-send" learned to ask the credential helper for auth
   material.

 * "git log" and friends now understand the value "auto" set to the
   "log.decorate" configuration variable to enable the "--decorate"
   option automatically when the output is sent to tty.

 * "git merge" without argument, even when there is an upstream
   defined for the current branch, refused to run until
   merge.defaultToUpstream is set to true.  Flip the default of that
   configuration variable to true.

 * "git mergetool" learned to drive the vimdiff3 backend.

 * mergetool.prompt used to default to 'true', always asking "do you
   really want to run the tool on this path?".  Among the two
   purposes this prompt serves, ignore the use case to confirm that
   the user wants to view particular path with the named tool, and
   redefine the meaning of the prompt only to confirm the choice of
   the tool made by the autodetection (for those who configured the
   tool explicitly, the prompt shown for the latter purpose is
   simply annoying).

   Strictly speaking, this is a backward incompatible change and the
   users need to explicitly set the variable to 'true' if they want
   to resurrect the now-ignored use case.

 * "git replace" learned the "--edit" subcommand to create a
   replacement by editing an existing object.

 * "git replace" learned a "--graft" option to rewrite parents of a
   commit.

 * "git send-email" learned "--to-cover" and "--cc-cover" options, to
   tell it to copy To: and Cc: headers found in the first input file
   when emitting later input files.

 * "git svn" learned to cope with malformed timestamps with only one
   digit in the hour part, e.g. 2014-01-07T5:01:02.048176Z, emitted
   by some broken subversion server implementations.

 * "git tag" when editing the tag message shows the name of the tag
   being edited as a comment in the editor.

 * "git tag" learned to pay attention to "tag.sort" configuration, to
   be used as the default sort order when no --sort=<value> the option
   is given.

 * "git verify-commit" command to check GPG signature in signed
   commits, in a way similar to "git verify-tag" is used to check
   signed tags, was added.


Performance, Internal Implementation, etc.

 * Build procedure for 'subtree' (in contrib/) has been cleaned up.

 * The support for the profile-feedback build, which has been left
   bit-rotten for quite a while, has been updated.

 * An experimental format to use two files (the base file and
   incremental changes relative to it) to represent the index has been
   introduced; this may reduce I/O cost of rewriting a large index
   when only small part of the working tree changes.

 * Effort to shrink the size of patches Windows folks maintain on top
   by upstreaming them continues.

 * Patches maintained by msysgit folks for Windows port are being
   upstreamed here a bit by bit.

 * The leaf function to check validity of a refname format has been
   micro-optimized, using SSE2 instructions when available.  A few
   breakages during its development have been caught and fixed already
   but there might remain some more still; please test and report if
   you find any.

 * The `core.deltabasecachelimit` used to default to 16 MiB , but this
   proved to be too small, and has been bumped to 96 MiB.

 * "git blame" has been optimized greatly by reorganising the data
   structure that is used to keep track of the work to be done.

 * "git diff" that compares 3-or-more trees (e.g. parents and the
   result of a merge) have been optimized.

 * The API to update/delete references are being converted to handle
   updates to multiple references in a transactional way.  As an
   example, "update-ref --stdin [-z]" has been updated to use this
   API.

 * skip_prefix() and strip_suffix() API functions are used a lot more
   widely throughout the codebase now.

 * Parts of the test scripts can be skipped by using a range notation,
   e.g. "sh t1234-test.sh --run='1-4 6 8-'" to omit test piece 5 and 7
   and run everything else.


Also contains various documentation updates and code clean-ups.


Fixes since v2.0
----------------

Unless otherwise noted, all the fixes since v2.0 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * We used to unconditionally disable the pager in the pager process
   we spawn to feed out output, but that prevented people who want to
   run "less" within "less" from doing so.
   (merge c0459ca je/pager-do-not-recurse later to maint).

 * Tools that read diagnostic output in our standard error stream do
   not want to see terminal control sequence (e.g. erase-to-eol).
   Detect them by checking if the standard error stream is connected
   to a tty.
   (merge 38de156 mn/sideband-no-ansi later to maint).

 * Mishandling of patterns in .gitignore that has trailing SPs quoted
   with backslashes (e.g. ones that end with "\ ") have been
   corrected.
   (merge 97c1364be6b pb/trim-trailing-spaces later to maint).

 * Reworded the error message given upon a failure to open an existing
   loose object file due to e.g. permission issues; it was reported as
   the object being corrupt, but that is not quite true.
   (merge d6c8a05 jk/report-fail-to-read-objects-better later to maint).

 * "git log -2master" is a common typo that shows two commits starting
   from whichever random branch that is not 'master' that happens to
   be checked out currently.
   (merge e3fa568 jc/revision-dash-count-parsing later to maint).

 * Code to avoid adding the same alternate object store twice was
   subtly broken for a long time, but nobody seems to have noticed.
   (merge 80b4785 rs/fix-alt-odb-path-comparison later to maint).
   (merge 539e750 ek/alt-odb-entry-fix later to maint).

 * The "%<(10,trunc)%s" pretty format specifier in the log family of
   commands is used to truncate the string to a given length (e.g. 10
   in the example) with padding to column-align the output, but did
   not take into account that number of bytes and number of display
   columns are different.
   (merge 7d50987 as/pretty-truncate later to maint).

 * "%G" (nothing after G) is an invalid pretty format specifier, but
   the parser did not notice it as garbage.
   (merge 958b2eb jk/pretty-G-format-fixes later to maint).

 * A handful of code paths had to read the commit object more than
   once when showing header fields that are usually not parsed.  The
   internal data structure to keep track of the contents of the commit
   object has been updated to reduce the need for this double-reading,
   and to allow the caller find the length of the object.
   (merge 218aa3a jk/commit-buffer-length later to maint).

 * The "mailmap.file" configuration option did not support the tilde
   expansion (i.e. ~user/path and ~/path).
   (merge 9352fd5 ow/config-mailmap-pathname later to maint).

 * The completion scripts (in contrib/) did not know about quite a few
   options that are common between "git merge" and "git pull", and a
   couple of options unique to "git merge".
   (merge 8fee872 jk/complete-merge-pull later to maint).

 * The unix-domain socket used by the sample credential cache daemon
   tried to unlink an existing stale one at a wrong path, if the path
   to the socket was given as an overlong path that does not fit in
   sun_path member of the sockaddr_un structure.
   (merge 2869b3e rs/fix-unlink-unix-socket later to maint).

 * An ancient rewrite passed a wrong pointer to a curl library
   function in a rarely used code path.
   (merge 479eaa8 ah/fix-http-push later to maint).

 * "--ignore-space-change" option of "git apply" ignored the spaces
   at the beginning of line too aggressively, which is inconsistent
   with the option of the same name "diff" and "git diff" have.
   (merge 14d3bb4 jc/apply-ignore-whitespace later to maint).

 * "git blame" miscounted number of columns needed to show localized
   timestamps, resulting in jaggy left-side-edge of the source code
   lines in its output.
   (merge dd75553 jx/blame-align-relative-time later to maint).

 * "git blame" assigned the blame to the copy in the working-tree if
   the repository is set to core.autocrlf=input and the file used CRLF
   line endings.
   (merge 4d4813a bc/blame-crlf-test later to maint).

 * "git clone -b brefs/tags/bar" would have mistakenly thought we were
   following a single tag, even though it was a name of the branch,
   because it incorrectly used strstr().
   (merge 60a5f5f jc/fix-clone-single-starting-at-a-tag later to maint).

 * "git commit --allow-empty-messag -C $commit" did not work when the
   commit did not have any log message.
   (merge 076cbd6 jk/commit-C-pick-empty later to maint).

 * "git diff --find-copies-harder" sometimes pretended as if the mode
   bits have changed for paths that are marked with assume-unchanged
   bit.
   (merge 5304810 jk/diff-files-assume-unchanged later to maint).

 * "filter-branch" left an empty single-parent commit that results when
   all parents of a merge commit gets mapped to the same commit, even
   under "--prune-empty".
   (merge 79bc4ef cb/filter-branch-prune-empty-degenerate-merges later to maint).

 * "git format-patch" did not enforce the rule that the "--follow"
   option from the log/diff family of commands must be used with
   exactly one pathspec.
   (merge dd63f16 jk/diff-follow-must-take-one-pathspec later to maint).

 * "git gc --auto" was recently changed to run in the background to
   give control back early to the end-user sitting in front of the
   terminal, but it forgot that housekeeping involving reflogs should
   be done without other processes competing for accesses to the refs.
   (merge 62aad18 nd/daemonize-gc later to maint).

 * "git grep -O" to show the lines that hit in the pager did not work
   well with case insensitive search.  We now spawn "less" with its
   "-I" option when it is used as the pager (which is the default).
   (merge f7febbe sk/spawn-less-case-insensitively-from-grep-O-i later to maint).

 * We used to disable threaded "git index-pack" on platforms without
   thread-safe pread(); use a different workaround for such
   platforms to allow threaded "git index-pack".
   (merge 3953949 nd/index-pack-one-fd-per-thread later to maint).

 * The error reporting from "git index-pack" has been improved to
   distinguish missing objects from type errors.
   (merge 77583e7 jk/index-pack-report-missing later to maint).

 * "log --show-signature" incorrectly decided the color to paint a
   mergetag that was and was not correctly validated.
   (merge 42c55ce mg/fix-log-mergetag-color later to maint).

 * "log --show-signature" did not pay attention to "--graph" option.
   (merge cf3983d zk/log-graph-showsig later to maint).

 * "git mailinfo" used to read beyond the end of header string while
   parsing an incoming e-mail message to extract the patch.
   (merge b1a013d rs/mailinfo-header-cmp later to maint).

 * On a case insensitive filesystem, merge-recursive incorrectly
   deleted the file that is to be renamed to a name that is the same
   except for case differences.
   (merge baa37bf dt/merge-recursive-case-insensitive later to maint).

 * Merging changes into a file that ends in an incomplete line made the
   last line into a complete one, even when the other branch did not
   change anything around the end of file.
   (merge ba31180 mk/merge-incomplete-files later to maint).

 * "git pack-objects" unnecessarily copied the previous contents when
   extending the hashtable, even though it will populate the table
   from scratch anyway.
   (merge fb79947 rs/pack-objects-no-unnecessary-realloc later to maint).

 * Recent updates to "git repack" started to duplicate objects that
   are in packfiles marked with .keep flag into the new packfile by
   mistake.
   (merge d078d85 jk/repack-pack-keep-objects later to maint).

 * "git rerere forget" did not work well when merge.conflictstyle
   was set to a non-default value.
   (merge de3d8bb fc/rerere-conflict-style later to maint).

 * "git remote rm" and "git remote prune" can involve removing many
   refs at once, which is not a very efficient thing to do when very
   many refs exist in the packed-refs file.
   (merge e6bea66 jl/remote-rm-prune later to maint).

 * "git log --exclude=<glob> --all | git shortlog" worked as expected,
   but "git shortlog --exclude=<glob> --all", which is supposed to be
   identical to the above pipeline, was not accepted at the command
   line argument parser level.
   (merge eb07774 jc/shortlog-ref-exclude later to maint).

 * The autostash mode of "git rebase -i" did not restore the dirty
   working tree state if the user aborted the interactive rebase by
   emptying the insn sheet.
   (merge ddb5432 rr/rebase-autostash-fix later to maint).

 * "git rebase --fork-point" did not filter out patch-identical
   commits correctly.

 * During "git rebase --merge", a conflicted patch could not be
   skipped with "--skip" if the next one also conflicted.
   (merge 95104c7 bc/fix-rebase-merge-skip later to maint).

 * "git show -s" (i.e. show log message only) used to incorrectly emit
   an extra blank line after a merge commit.
   (merge ad2f725 mk/show-s-no-extra-blank-line-for-merges later to maint).

 * "git status", even though it is a read-only operation, tries to
   update the index with refreshed lstat(2) info to optimize future
   accesses to the working tree opportunistically, but this could
   race with a "read-write" operation that modify the index while it
   is running.  Detect such a race and avoid overwriting the index.
   (merge 426ddee ym/fix-opportunistic-index-update-race later to maint).

 * "git status" (and "git commit") behaved as if changes in a modified
   submodule are not there if submodule.*.ignore configuration is set,
   which was misleading.  The configuration is only to unclutter diff
   output during the course of development, and should not to hide
   changes in the "status" output to cause the users forget to commit
   them.
   (merge c215d3d jl/status-added-submodule-is-never-ignored later to maint).

 * Documentation for "git submodule sync" forgot to say that the subcommand
   can take the "--recursive" option.
   (merge 9393ae7 mc/doc-submodule-sync-recurse later to maint).

 * "git update-index --cacheinfo" in 2.0 release crashed on a
   malformed command line.
   (merge c8e1ee4 jc/rev-parse-argh-dashed-multi-words later to maint).

 * The mode to run tests with HTTP server tests disabled was broken.
   (merge afa53fe na/no-http-test-in-the-middle later to maint).

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

Changes since v2.0.0, 643 non-merge changes from 80 contributors,
are as follows:

Abbaad Haider (1):
      http-push.c: make CURLOPT_IOCTLDATA a usable pointer

Alexey Shumkin (5):
      t4205 (log-pretty-formats): don't hardcode SHA-1 in expected outputs
      t4041, t4205, t6006, t7102: don't hardcode tested encoding value
      t4205 (log-pretty-format): use `tformat` rather than `format`
      t4205, t6006: add tests that fail with i18n.logOutputEncoding set
      pretty.c: format string with truncate respects logOutputEncoding

Anders Kaseorg (1):
      gitk: Allow displaying time zones from author and commit dates timestamps

Andi Kleen (4):
      Use BASIC_FLAGS for profile feedback
      Don't define away __attribute__ on gcc
      Run the perf test suite for profile feedback too
      Fix profile feedback with -jN and add profile-fast

Andreas Schwab (1):
      grep: add grep.fullName config variable

Ben Walton (1):
      compat/bswap.h: fix endianness detection

Brian Gesiak (14):
      strbuf: use _rtrim and _ltrim in strbuf_trim
      api-strbuf.txt: add docs for _trim and _ltrim
      builtin/ls-remote.c: rearrange xcalloc arguments
      builtin/remote.c: rearrange xcalloc arguments
      commit.c: rearrange xcalloc arguments
      config.c: rearrange xcalloc arguments
      diff.c: rearrange xcalloc arguments
      http-push.c: rearrange xcalloc arguments
      imap-send.c: rearrange xcalloc arguments
      notes.c: rearrange xcalloc arguments
      pack-revindex.c: rearrange xcalloc arguments
      reflog-walk.c: rearrange xcalloc arguments
      remote.c: rearrange xcalloc arguments
      transport-helper.c: rearrange xcalloc arguments

Cezary Zawadka (1):
      Windows: allow using UNC path for git repository

Charles Bailey (3):
      compat/bswap.h: detect endianness on more platforms that don't use BYTE_ORDER
      filter-branch: eliminate duplicate mapped parents
      Fix contrib/subtree Makefile to patch #! line

Christian Couder (16):
      replace: make sure --edit results in a different object
      replace: refactor checking ref validity
      replace: die early if replace ref already exists
      replace: add tests for --edit
      replace: add --edit to usage string
      Documentation: replace: describe new --edit option
      commit: add for_each_mergetag()
      replace: cleanup redirection style in tests
      replace: add --graft option
      replace: add test for --graft
      Documentation: replace: add --graft option
      contrib: add convert-grafts-to-replace-refs.sh
      replace: remove signature when using --graft
      replace: add test for --graft with signed commit
      replace: check mergetags when using --graft
      replace: add test for --graft with a mergetag

Dan Albert (1):
      imap-send: use git-credential

David Aguilar (3):
      gitk: Honor TMPDIR when viewing external diffs
      gitk: Use mktemp -d to avoid predictable temporary directories
      gitk: Catch mkdtemp errors

David Kastrup (2):
      blame: large-scale performance rewrite
      Bump core.deltaBaseCacheLimit to 96m

David Turner (7):
      docs: document RUN_SETUP_GENTLY and clarify RUN_SETUP
      merge-recursive.c: fix case-changing merge bug
      mv: allow renaming to fix case on case insensitive filesystems
      refs.c: optimize check_refname_component()
      refs.c: SSE2 optimizations for check_refname_component
      refs.c: handle REFNAME_REFSPEC_PATTERN at end of page
      refs: fix valgrind suppression file

Elia Pinto (62):
      t9365-continuing-queries.sh: use the $( ... ) construct for command substitution
      test-gitmw-lib.sh: use the $( ... ) construct for command substitution
      t7900-subtree.sh: use the $( ... ) construct for command substitution
      appp.sh: use the $( ... ) construct for command substitution
      git-pull.sh: use the $( ... ) construct for command substitution
      git-rebase--merge.sh: use the $( ... ) construct for command substitution
      git-rebase.sh: use the $( ... ) construct for command substitution
      git-stash.sh: use the $( ... ) construct for command substitution
      git-web--browse.sh: use the $( ... ) construct for command substitution
      lib-credential.sh: use the $( ... ) construct for command substitution
      lib-cvs.sh: use the $( ... ) construct for command substitution
      lib-gpg.sh: use the $( ... ) construct for command substitution
      p5302-pack-index.sh: use the $( ... ) construct for command substitution
      t0001-init.sh: use the $( ... ) construct for command substitution
      t0010-racy-git.sh: use the $( ... ) construct for command substitution
      t0020-crlf.sh: use the $( ... ) construct for command substitution
      t0025-crlf-auto.sh: use the $( ... ) construct for command substitution
      t0026-eol-config.sh: use the $( ... ) construct for command substitution
      t0030-stripspace.sh: use the $( ... ) construct for command substitution
      t0300-credentials.sh: use the $( ... ) construct for command substitution
      t1000-read-tree-m-3way.sh: use the $( ... ) construct for command substitution
      t1001-read-tree-m-2way.sh: use the $( ... ) construct for command substitution
      t1002-read-tree-m-u-2way.sh: use the $( ... ) construct for command substitution
      t1003-read-tree-prefix.sh: use the $( ... ) construct for command substitution
      t1004-read-tree-m-u-wf.sh: use the $( ... ) construct for command substitution
      t1020-subdirectory.sh: use the $( ... ) construct for command substitution
      t1050-large.sh: use the $( ... ) construct for command substitution
      t3905-stash-include-untracked.sh: use the $( ... ) construct for command substitution
      t3910-mac-os-precompose.sh: use the $( ... ) construct for command substitution
      t4006-diff-mode.sh: use the $( ... ) construct for command substitution
      t4010-diff-pathspec.sh: use the $( ... ) construct for command substitution
      t4012-diff-binary.sh: use the $( ... ) construct for command substitution
      t4013-diff-various.sh: use the $( ... ) construct for command substitution
      t4014-format-patch.sh: use the $( ... ) construct for command substitution
      t4036-format-patch-signer-mime.sh: use the $( ... ) construct for command substitution
      t4038-diff-combined.sh: use the $( ... ) construct for command substitution
      t4057-diff-combined-paths.sh: use the $( ... ) construct for command substitution
      t4116-apply-reverse.sh: use the $( ... ) construct for command substitution
      t4119-apply-config.sh: use the $( ... ) construct for command substitution
      t4204-patch-id.sh: use the $( ... ) construct for command substitution
      t5000-tar-tree.sh: use the $( ... ) construct for command substitution
      scripts: "export VAR=VALUE" construct is not portable
      check_bindir: avoid "test <cond> -a/-o <cond>"
      contrib/examples/git-clone.sh: avoid "test <cond> -a/-o <cond>"
      contrib/examples/git-commit.sh: avoid "test <cond> -a/-o <cond>"
      contrib/examples/git-merge.sh: avoid "test <cond> -a/-o <cond>"
      contrib/examples/git-repack.sh: avoid "test <cond> -a/-o <cond>"
      contrib/examples/git-resolve.sh: avoid "test <cond> -a/-o <cond>"
      git-bisect.sh: avoid "test <cond> -a/-o <cond>"
      git-mergetool.sh: avoid "test <cond> -a/-o <cond>"
      git-rebase--interactive.sh: avoid "test <cond> -a/-o <cond>"
      t/lib-httpd.sh: avoid "test <cond> -a/-o <cond>"
      t/t0025-crlf-auto.sh: avoid "test <cond> -a/-o <cond>"
      t/t0026-eol-config.sh: avoid "test <cond> -a/-o <cond>"
      t/t4102-apply-rename.sh: avoid "test <cond> -a/-o <cond>"
      t/t5000-tar-tree.sh: avoid "test <cond> -a/-o <cond>"
      t/t5403-post-checkout-hook.sh: avoid "test <cond> -a/-o <cond>"
      t/t5538-push-shallow.sh: avoid "test <cond> -a/-o <cond>"
      t/t9814-git-p4-rename.sh: avoid "test <cond> -a/-o <cond>"
      t/test-lib-functions.sh: avoid "test <cond> -a/-o <cond>"
      git-submodule.sh: avoid "test <cond> -a/-o <cond>"
      submodule.c: use the ARRAY_SIZE macro

Ephrim Khong (1):
      sha1_file: do not add own object directory as alternate

Eric Wong (1):
      config: preserve config file permissions on edits

Erik Faye-Lund (1):
      send-email: recognize absolute path on Windows

Fabian Ruch (1):
      sequencer: signal failed ff as an aborted, not a conflicted merge

Felipe Contreras (13):
      fast-export: improve argument parsing
      fast-export: add new --refspec option
      transport-helper: add support for old:new refspec
      transport-helper: add support to push symbolic refs
      fast-import: add support to delete refs
      fast-export: add support to delete refs
      transport-helper: add support to delete branches
      transport-helper: remove unnecessary strbuf resets
      mergetools: add vimdiff3 mode
      mergetool: run prompt only if guessed tool
      merge: enable defaulttoupstream by default
      rerere: fix for merge.conflictstyle
      silence a bunch of format-zero-length warnings

Ilya Bobyr (4):
      test-lib: document short options in t/README
      test-lib: tests skipped by GIT_SKIP_TESTS say so
      test-lib: '--run' to run only specific tests
      gitk: Replace SHA1 entry field on keyboard paste

Jacek Konieczny (1):
      pull: do not abuse 'break' inside a shell 'case'

Jacob Keller (2):
      tag: fix --sort tests to use cat<<-\EOF format
      tag: support configuring --sort via .gitconfig

James Denholm (6):
      contrib/subtree/Makefile: scrap unused $(gitdir)
      contrib/subtree/Makefile: use GIT-VERSION-FILE
      contrib/subtree/Makefile: s/libexecdir/gitexecdir/
      contrib/subtree/Makefile: clean up rules to generate documentation
      contrib/subtree/Makefile: clean up rule for "clean"
      contrib/subtree: allow adding an annotated tag

Jason St. John (1):
      Documentation: use "command-line" when used as a compound adjective, and fix other minor grammatical issues

Jean-Jacques Lafay (1):
      git tag --contains: avoid stack overflow

Jeff King (131):
      run_external_diff: use an argv_array for the environment
      run_external_diff: clean up error handling
      run_external_diff: drop fflush(NULL)
      run_external_diff: hoist common bits out of conditional
      run_external_diff: refactor cmdline setup logic
      commit: do not complain of empty messages from -C
      t3910: show failure of core.precomposeunicode with decomposed filenames
      replace: refactor command-mode determination
      replace: use OPT_CMDMODE to handle modes
      replace: factor object resolution out of replace_object
      replace: add --edit option
      commit: use split_ident_line to compare author/committer
      pretty: make show_ident_date public
      commit: print "Date" line when the user has set date
      commit: accept more date formats for "--date"
      inline constant return from error() function
      let clang use the constant-return error() macro
      grep: use run-command's "dir" option for --open-files-in-pager
      t/lib-httpd: require SANITY prereq
      index-pack: distinguish missing objects from type errors
      run_diff_files: do not look at uninitialized stat data
      run-command: store an optional argv_array
      run_column_filter: use argv_array
      git_connect: use argv_array
      get_helper: use run-command's internal argv_array
      get_exporter: use argv_array
      get_importer: use run-command's internal argv_array
      argv-array: drop "detach" code
      open_sha1_file: report "most interesting" errno
      move "--follow needs one pathspec" rule to diff_setup_done
      format-patch: make newline after signature conditional
      daemon/config: factor out duplicate xstrdup_tolower
      test-lib: preserve GIT_CURL_VERBOSE from the environment
      t/lib-httpd: use write_script to copy CGI scripts
      t5550: test display of remote http error messages
      strbuf: add strbuf_tolower function
      http: extract type/subtype portion of content-type
      http: optionally extract charset parameter from content-type
      strbuf: add strbuf_reencode helper
      remote-curl: reencode http error messages
      http: default text charset to iso-8859-1
      t5537: re-drop http tests
      error_resolve_conflict: rewrap advice message
      error_resolve_conflict: drop quotations around operation
      update-index: fix segfault with missing --cacheinfo argument
      repack: do not accidentally pack kept objects by default
      repack: respect pack.writebitmaps
      repack: s/write_bitmap/&s/ in code
      pack-objects: stop respecting pack.writebitmaps
      repack: simplify handling of --write-bitmap-index
      repack: introduce repack.writeBitmaps config option
      commit_tree: take a pointer/len pair rather than a const strbuf
      replace dangerous uses of strbuf_attach
      alloc: include any-object allocations in alloc_report
      commit: push commit_index update into alloc_commit_node
      do not create "struct commit" with xcalloc
      logmsg_reencode: return const buffer
      sequencer: use logmsg_reencode in get_message
      t7700: drop explicit --no-pack-kept-objects from .keep test
      provide a helper to free commit buffer
      provide a helper to set the commit buffer
      provide helpers to access the commit buffer
      use get_cached_commit_buffer where appropriate
      use get_commit_buffer to avoid duplicate code
      convert logmsg_reencode to get_commit_buffer
      use get_commit_buffer everywhere
      commit-slab: provide a static initializer
      commit: convert commit->buffer to a slab
      commit: record buffer length in cache
      reuse cached commit buffer when parsing signatures
      t7510: stop referring to master in later tests
      t7510: test a commit signed by an unknown key
      t7510: check %G* pretty-format output
      pretty: avoid reading past end-of-string with "%G"
      parse_diff_color_slot: drop ofs parameter
      daemon: mark some strings as const
      avoid using skip_prefix as a boolean
      strbuf: add xstrfmt helper
      use xstrfmt in favor of manual size calculations
      use xstrdup instead of xmalloc + strcpy
      use xstrfmt to replace xmalloc + sprintf
      use xstrfmt to replace xmalloc + strcpy/strcat
      setup_git_env: use git_pathdup instead of xmalloc + sprintf
      sequencer: use argv_array_pushf
      merge: use argv_array when spawning merge strategy
      walker_fetch: fix minor memory leak
      unique_path: fix unlikely heap overflow
      refactor skip_prefix to return a boolean
      apply: use skip_prefix instead of raw addition
      fast-import: fix read of uninitialized argv memory
      transport-helper: avoid reading past end-of-string
      use skip_prefix to avoid magic numbers
      use skip_prefix to avoid repeating strings
      fast-import: use skip_prefix for parsing input
      daemon: use skip_prefix to avoid magic numbers
      stat_opt: check extra strlen call
      fast-import: refactor parsing of spaces
      fetch-pack: refactor parsing in get_ack
      git: avoid magic number with skip_prefix
      use skip_prefix to avoid repeated calculations
      http-push: refactor parsing of remote object names
      setup_git_env(): introduce git_path_from_env() helper
      move "%G" format test from t7510 to t6006
      replace: replace spaces with tabs in indentation
      avoid double close of descriptors handed to run_command
      replace: use argv_array in export_object
      replace: add a --raw mode for --edit
      add strip_suffix function
      implement ends_with via strip_suffix
      replace has_extension with ends_with
      use strip_suffix instead of ends_with in simple cases
      index-pack: use strip_suffix to avoid magic numbers
      strbuf: implement strbuf_strip_suffix
      verify-pack: use strbuf_strip_suffix
      prepare_packed_git_one: refactor duplicate-pack check
      t7300: repair filesystem permissions with test_when_finished
      remote-curl: do not complain on EOF from parent git
      remote-curl: use error instead of fprintf(stderr)
      remote-curl: mark helper-protocol errors more clearly
      tag: use skip_prefix instead of magic numbers
      alloc: write out allocator definitions
      move setting of object->type to alloc_* functions
      parse_object_buffer: do not set object type
      add object_as_type helper for casting objects
      alloc: factor out commit index
      object_as_type: set commit index
      diff-tree: avoid lookup_unknown_object
      prio-queue: factor out compare and swap operations
      prio-queue: make output stable with respect to insertion
      paint_down_to_common: use prio_queue
      t5539: update a flaky test

Jens Lehmann (21):
      status/commit: show staged submodules regardless of ignore config
      commit -m: commit staged submodules regardless of ignore config
      git-gui: show staged submodules regardless of ignore config
      git-gui: tolerate major version changes when comparing the git version
      gitk: Show staged submodules regardless of ignore config
      test-lib: add test_dir_is_empty()
      t/Makefile: check helper scripts for non-portable shell commands too
      t/Makefile: always test all lint targets when running tests
      submodules: add the lib-submodule-update.sh test library
      checkout: call the new submodule update test framework
      apply: add t4137 for submodule updates
      read-tree: add t1013 for submodule updates
      reset: add t7112 for submodule updates
      bisect: add t6041 for submodule updates
      merge: add t7613 for submodule updates
      rebase: add t3426 for submodule updates
      pull: add t5572 for submodule updates
      cherry-pick: add t3512 for submodule updates
      am: add t4255 for submodule updates
      stash: add t3906 for submodule updates
      revert: add t3513 for submodule updates

Jens Lindström (3):
      remote rm: delete remote configuration as the last
      remote: repack packed-refs once when deleting multiple refs
      remote prune: optimize "dangling symref" check/warning

Jeremiah Mahler (7):
      format-patch: add "--signature-file=<file>" option
      t9138-git-svn-authors-prog.sh fixups
      Documentation: wording fixes in the user manual and glossary
      t/t7810-grep.sh: remove duplicate test_config()
      api-strbuf.txt minor typos
      name-hash.c: replace cache_name_compare() with memcmp(3)
      cleanup duplicate name_compare() functions

Jiang Xin (2):
      blame: fix broken time_buf paddings in relative timestamp
      blame: dynamic blame_date_width for different locales

Johannes Schindelin (2):
      git grep -O -i: if the pager is 'less', pass the '-I' option
      Win32: let mingw_execve() return an int

Johannes Sixt (1):
      fix brown paper bag breakage in t5150-request-pull.sh

John Keeping (4):
      completion: add a note that merge options are shared
      completion: add missing options for git-merge
      rebase--am: use --cherry-pick instead of --ignore-if-in-upstream
      rebase: omit patch-identical commits with --fork-point

Jonathan McCrohan (1):
      git-instaweb: add support for Apache 2.4

Jonathan Nieder (4):
      contrib: remove vim support instructions
      contrib: remove git-diffall
      test-lint: find unportable sed, echo, test, and export usage after &&
      test doc: test_write_lines does not split its arguments

Junio C Hamano (49):
      apply --ignore-space-change: lines with and without leading whitespaces do not match
      send-email: windows drive prefix (e.g. C:) appears only at the beginning
      mergetool: document the default for --[no-]prompt
      compat/bswap.h: restore preference __BIG_ENDIAN over BIG_ENDIAN
      CodingGuidelines: once it is in, it is not worth the code churn
      CodingGuidelines: give an example for case/esac statement
      CodingGuidelines: give an example for redirection
      CodingGuidelines: give an example for control statements
      CodingGuidelines: give an example for shell function preamble
      CodingGuidelines: do not call the conditional statement "if()"
      CodingGuidelines: on comparison
      CodingGuidelines: on splitting a long line
      CodingGuidelines: avoid "test <cond> -a/-o <cond>"
      scripts: more "export VAR=VALUE" fixes
      Git 1.9.4
      fetch doc: update introductory part for clarity
      fetch doc: update note on '+' in front of the refspec
      fetch doc: remove notes on outdated "mixed layout"
      First batch for 2.1
      shortlog: allow --exclude=<glob> to be passed
      fetch doc: on pulling multiple refspecs
      fetch doc: update refspec format description
      fetch doc: remove "short-cut" section
      fetch doc: add a section on configured remote-tracking branches
      fetch: allow explicit --refmap to override configuration
      Second batch for 2.1
      Update draft release notes to 2.1
      test: turn EXPENSIVE into a lazy prerequisite
      test: turn USR_BIN_TIME into a lazy prerequisite
      t3302: coding style updates
      t3302: do not chdir around in the primary test process
      t3302: drop unnecessary NOT_EXPENSIVE pseudo-prerequisite
      t3419: drop unnecessary NOT_EXPENSIVE pseudo-prerequisite
      revision: parse "git log -<count>" more carefully
      t0008: do not depend on 'echo' handling backslashes specially
      Third batch for 2.1
      git-submodule.sh: avoid "echo" path-like values
      Fourth batch for 2.1
      builtin/clone.c: detect a clone starting at a tag correctly
      Git 2.0.1
      Fifth batch for 2.1
      Sixth batch for 2.1
      Start preparing for 2.0.2
      Seventh batch for 2.1
      Git 2.0.2
      Eighth batch for 2.1
      Ninth batch for 2.1
      Git 2.0.3
      Git 2.1.0-rc0

Jörn Engel (1):
      pager: do allow spawning pager recursively

Karsten Blees (46):
      MSVC: link dynamically to the CRT
      Win32 dirent: remove unused dirent.d_ino member
      Win32 dirent: remove unused dirent.d_reclen member
      Win32 dirent: change FILENAME_MAX to MAX_PATH
      Win32 dirent: clarify #include directives
      Win32 dirent: improve dirent implementation
      Win32: move main macro to a function
      Win32: support Unicode console output
      Win32: detect console streams more reliably
      Win32: warn if the console font doesn't support Unicode
      Win32: add Unicode conversion functions
      Win32: Thread-safe windows console output
      Win32: fix broken pipe detection
      Win32: reliably detect console pipe handles
      Win32: simplify internal mingw_spawn* APIs
      Win32: fix potential multi-threading issue
      MinGW: disable CRT command line globbing
      Win32: Unicode arguments (outgoing)
      Win32: Unicode arguments (incoming)
      trace: move trace declarations from cache.h to new trace.h
      trace: consistently name the format parameter
      trace: remove redundant printf format attribute
      symlinks: remove PATH_MAX limitation
      hashmap: factor out getting a hash code from a SHA1
      hashmap: improve struct hashmap member documentation
      hashmap: add simplified hashmap_get_from_hash() API
      hashmap: add string interning API
      cache.h: rename cache_def_free to cache_def_clear
      trace: improve trace performance
      Documentation/git.txt: improve documentation of 'GIT_TRACE*' variables
      sha1_file: change GIT_TRACE_PACK_ACCESS logging to use trace API
      trace: add infrastructure to augment trace output with additional info
      trace: disable additional trace output for unit tests
      trace: add current timestamp to all trace output
      trace: move code around, in preparation to file:line output
      trace: add 'file:line' to all trace output
      trace: add high resolution timer function to debug performance issues
      trace: add trace_performance facility to debug performance issues
      git: add performance tracing for git's main() function to debug scripts
      wt-status: simplify performance measurement by using getnanotime()
      progress: simplify performance measurement by using getnanotime()
      api-trace.txt: add trace API documentation
      Win32: Unicode file name support (except dirent)
      Win32: Unicode file name support (dirent)
      MinGW: fix compile error due to missing ELOOP
      config: use chmod() instead of fchmod()

Kirill Smelkov (20):
      combine-diff: move show_log_first logic/action out of paths scanning
      combine-diff: move changed-paths scanning logic into its own function
      tree-diff: no need to manually verify that there is no mode change for a path
      tree-diff: no need to pass match to skip_uninteresting()
      tree-diff: show_tree() is not needed
      tree-diff: consolidate code for emitting diffs and recursion in one place
      tree-diff: don't assume compare_tree_entry() returns -1,0,1
      tree-diff: move all action-taking code out of compare_tree_entry()
      tree-diff: rename compare_tree_entry -> tree_entry_pathcmp
      tree-diff: show_path prototype is not needed anymore
      tree-diff: simplify tree_entry_pathcmp
      tree-diff: remove special-case diff-emitting code for empty-tree cases
      tree-diff: diff_tree() should now be static
      tree-diff: rework diff_tree interface to be sha1 based
      tree-diff: no need to call "full" diff_tree_sha1 from show_path()
      tree-diff: reuse base str(buf) memory on sub-tree recursion
      Portable alloca for Git
      tree-diff: rework diff_tree() to generate diffs for multiparent cases as well
      combine-diff: speed it up, by using multiparent diff tree-walker directly
      mingw: activate alloca

Linus Torvalds (1):
      git log: support "auto" decorations

Luis R. Rodriguez (1):
      git.c: treat RUN_SETUP_GENTLY and RUN_SETUP as mutually exclusive

Marc Branchaud (2):
      fetch doc: move FETCH_HEAD material lower and add an example
      docs: Explain the purpose of fetch's and pull's <refspec> parameter.

Matthew Chen (1):
      submodule: document "sync --recursive"

Matthieu Moy (4):
      git-remote-mediawiki: allow stop/start-ing the test server
      git-remote-mediawiki: fix encoding issue for UTF-8 media files
      pager: remove 'S' from $LESS by default
      rebase -i: test "Nothing to do" case with autostash

Max Kirillov (5):
      git-show: fix 'git show -s' to not add extra terminator after merge commit
      gitk: Switch to patch mode when searching for line origin
      gitk: Add visiblerefs option, which lists always-shown branches
      t6023-merge-file.sh: fix and mark as broken invalid tests
      git-merge-file: do not add LF at EOF while applying unrelated change

Maxime Coste (2):
      git-p4: Do not include diff in spec file when just preparing p4
      git-p4: fix submit in non --prepare-p4-only mode

Michael Barabanov (1):
      use local cloning if insteadOf makes a local URL

Michael Haggerty (27):
      t1400: fix name and expected result of one test
      t1400: provide more usual input to the command
      parse_arg(): really test that argument is properly terminated
      t1400: add some more tests involving quoted arguments
      refs.h: rename the action_on_err constants
      update_refs(): fix constness
      update-ref --stdin: read the whole input at once
      parse_cmd_verify(): copy old_sha1 instead of evaluating <oldvalue> twice
      update-ref.c: extract a new function, parse_refname()
      update-ref --stdin: improve error messages for invalid values
      update-ref --stdin: make error messages more consistent
      update-ref --stdin: simplify error messages for missing oldvalues
      t1400: test that stdin -z update treats empty <newvalue> as zeros
      update-ref.c: extract a new function, parse_next_sha1()
      update-ref --stdin -z: deprecate interpreting the empty string as zeros
      t1400: test one mistake at a time
      update-ref --stdin: improve the error message for unexpected EOF
      update-ref --stdin: harmonize error messages
      refs: add a concept of a reference transaction
      update-ref --stdin: reimplement using reference transactions
      refs: remove API function update_refs()
      struct ref_update: rename field "ref_name" to "refname"
      struct ref_update: store refname as a FLEX_ARRAY
      ref_transaction_commit(): simplify code using temporary variables
      struct ref_update: add a lock field
      struct ref_update: add a type field
      ref_transaction_commit(): work with transaction->updates in place

Michael J Gruber (7):
      t7510: use consistent &&-chains in loop
      gpg-interface: provide clear helper for struct signature_check
      gpg-interface: provide access to the payload
      verify-commit: scriptable commit signature verification
      t7510: exit for loop with test result
      t7510: test verify-commit
      log: correctly identify mergetag signature verification status

Michael Naumov (1):
      sideband.c: do not use ANSI control sequence on non-terminal

Michael S. Tsirkin (6):
      git-send-email: two new options: to-cover, cc-cover
      test/send-email: to-cover, cc-cover tests
      rebase --keep-empty -i: add test
      test: add test_write_lines helper
      patch-id: make it stable against hunk reordering
      patch-id-test: test stable and unstable behaviour

Nguyễn Thái Ngọc Duy (40):
      index-pack: work around thread-unsafe pread()
      ewah: fix constness of ewah_read_mmap
      ewah: delete unused ewah_read_mmap_native declaration
      sequencer: do not update/refresh index if the lock cannot be held
      config: be strict on core.commentChar
      commit: allow core.commentChar=auto for character auto selection
      gc --auto: do not lock refs in the background
      git potty: restore environments after alias expansion
      read-cache: new API write_locked_index instead of write_index/write_cache
      read-cache: relocate and unexport commit_locked_index()
      read-cache: store in-memory flags in the first 12 bits of ce_flags
      read-cache: be strict about "changed" in remove_marked_cache_entries()
      read-cache: be specific what part of the index has changed
      update-index: be specific what part of the index has changed
      resolve-undo: be specific what part of the index has changed
      unpack-trees: be specific what part of the index has changed
      cache-tree: mark istate->cache_changed on cache tree invalidation
      cache-tree: mark istate->cache_changed on cache tree update
      cache-tree: mark istate->cache_changed on prime_cache_tree()
      entry.c: update cache_changed if refresh_cache is set in checkout_entry()
      read-cache: save index SHA-1 after reading
      read-cache: split-index mode
      read-cache: mark new entries for split index
      read-cache: save deleted entries in split index
      read-cache: mark updated entries for split index
      split-index: the writing part
      split-index: the reading part
      split-index: do not invalidate cache-tree at read time
      split-index: strip pathname of on-disk replaced entries
      update-index: new options to enable/disable split index mode
      update-index --split-index: do not split if $GIT_DIR is read only
      rev-parse: add --shared-index-path to get shared index path
      read-tree: force split-index mode off on --index-output
      read-tree: note about dropping split-index mode or index version
      read-cache: force split index mode with GIT_TEST_SPLIT_INDEX
      t2104: make sure split index mode is off for the version test
      t1700: new tests for split-index mode
      dir.c: coding style fix
      dir.h: move struct exclude declaration to top level
      prep_exclude: remove the artificial PATH_MAX limit

Nick Alcock (1):
      t5538: move http push tests out to t5542

Pasha Bolokhov (1):
      dir.c:trim_trailing_spaces(): fix for " \ " sequence

Pat Thoyts (2):
      wincred: add install target
      wincred: avoid overwriting configured variables

Philip Oakley (1):
      doc: give some guidelines for error messages

Ramkumar Ramachandra (1):
      rebase -i: handle "Nothing to do" case with autostash

Ramsay Allan Jones (2):
      t0000-*.sh: fix the GIT_SKIP_TESTS sub-tests
      alloc.c: remove the alloc_raw_commit_node() function

René Scharfe (28):
      mailinfo: use strcmp() for string comparison
      pack-objects: use free()+xcalloc() instead of xrealloc()+memset()
      Use starts_with() for C strings instead of memcmp()
      blame: factor out get_next_line()
      blame: simplify prepare_lines()
      wt-status: use argv_array for environment
      wt-status: simplify building of summary limit argument
      sha1_file: replace PATH_MAX buffer with strbuf in prepare_packed_git_one()
      sha1_file: avoid overrunning alternate object base string
      t5000, t5003: simplify commit
      diff-tree: call free_commit_list() instead of duplicating its code
      line-log: use commit_list_append() instead of duplicating its code
      use strbuf_addbuf for adding strbufs
      use strbuf_addch for adding single characters
      merge: simplify merge_trivial() by using commit_list_append()
      commit: use commit_list_append() instead of duplicating its code
      fsck: simplify fsck_commit_buffer() by using commit_list_count()
      annotate: use argv_array
      strbuf: use strbuf_addstr() for adding C strings
      use commit_list_count() to count the members of commit_lists
      run-command: use internal argv_array of struct child_process in run_hook_ve()
      transport: simplify fetch_objs_via_rsync() using argv_array
      fast-import: use hashcmp() for SHA1 hash comparison
      bundle: use internal argv_array of struct child_process in create_bundle()
      remote-testsvn: use internal argv_array of struct child_process in cmd_import()
      unix-socket: remove stale socket before calling chdir()
      use xcalloc() to allocate zero-initialized memory
      use xmemdupz() to allocate copies of strings given by start and length

RomanBelinsky (1):
      SVN.pm::parse_svn_date: allow timestamps with a single-digit hour

Ronnie Sahlberg (27):
      sequencer.c: check for lock failure and bail early in fast_forward_to
      commit.c: check for lock error and return early
      refs.c: add new functions reflog_exists and delete_reflog
      checkout.c: use ref_exists instead of file_exist
      refs.c: change read_ref_at to use the reflog iterators
      enums: remove trailing ',' after last item in enum
      enums: remove trailing ',' after last item in enum
      refs.c: remove ref_transaction_rollback
      refs.c: ref_transaction_commit should not free the transaction
      refs.c: constify the sha arguments for ref_transaction_create|delete|update
      refs.c: allow passing NULL to ref_transaction_free
      refs.c: add a strbuf argument to ref_transaction_commit for error logging
      lockfile.c: add a new public function unable_to_lock_message
      lockfile.c: make lock_file return a meaningful errno on failurei
      refs.c: add an err argument to repack_without_refs
      refs.c: make sure log_ref_setup returns a meaningful errno
      refs.c: verify_lock should set errno to something meaningful
      refs.c: make remove_empty_directories always set errno to something sane
      refs.c: commit_packed_refs to return a meaningful errno on failure
      refs.c: make resolve_ref_unsafe set errno to something meaningful on error
      refs.c: log_ref_write should try to return meaningful errno
      refs.c: make ref_update_reject_duplicates take a strbuf argument for errors
      refs.c: make update_ref_write update a strbuf on failure
      update-ref: use err argument to get error from ref_transaction_commit
      refs.c: remove the onerr argument to ref_transaction_commit
      refs.c: change ref_transaction_update() to do error checking and return status
      refs.c: add a public is_branch function

Stefan Beller (3):
      .mailmap: map different names with the same email address together
      git.1: switch homepage for stats
      .mailmap: combine Stefan Beller's emails

Steffen Prohaska (1):
      completion: handle '!f() { ... }; f' and "!sh -c '...' -" aliases

Stepan Kasal (3):
      Revert "submodules: fix ambiguous absolute paths under Windows"
      t5000, t5003: do not use test_cmp to compare binary files
      mingw: avoid const warning

Stephen P. Smith (1):
      How to keep a project's canonical history correct.

Steve Hoelzer (1):
      environment.c: enable core.preloadindex by default

Tanay Abhra (4):
      string-list: spell all values out that are given to a string_list initializer
      imap-send: use skip_prefix instead of using magic numbers
      string-list: add string_list initializer helper function
      replace memset with string-list initializers

Theodore Leblond (1):
      compat/poll: sleep 1 millisecond to avoid busy wait

Thorsten Glaser (1):
      builtin/tag.c: show tag name to hint in the message editor

Torsten Bögershausen (7):
      utf8.c: use a table for double_width
      utf8: make it easier to auto-update git_wcwidth()
      t5551: fix the 50,000 tag test
      t9001: avoid non-portable '\n' with sed
      Update of unicode_width.h to Unicode Version 7.0
      t0025: rename the test files
      t0027: combinations of core.autocrlf, core.eol and text

Trần Ngọc Quân (1):
      l10n: Init Vietnamese translation

W. Trevor King (1):
      Documentation: mention config sources for @{upstream}

William Giokas (1):
      svn-fe: conform to pep8

Yi EungJun (2):
      http-protocol.txt: Basic Auth is defined in RFC 2617, not RFC 2616
      http: fix charset detection of extract_content_type()

Yiannis Marangos (2):
      wrapper.c: add xpread() similar to xread()
      read-cache.c: verify index file before we opportunistically update it

Zoltan Klinger (1):
      log: fix indentation for --graph --show-signature

brian m. carlson (3):
      blame: correctly handle files regardless of autocrlf
      rebase--merge: fix --skip with two conflicts in a row
      Documentation: fix missing text for rev-parse --verify

Øystein Walle (1):
      config: respect '~' and '~user' in mailmap.file

Øyvind A. Holm (1):
      .gitignore: "git-verify-commit" is a generated file

^ permalink raw reply	[relevance 3%]

* [ANNOUNCE] Git v2.1.0-rc2
@ 2014-08-08 22:17  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-08-08 22:17 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate Git v2.1.0-rc2 is now available for testing
at the usual places.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/testing/

The following public repositories all have a copy of the 'v2.1.0-rc2'
tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v2.1 Release Notes (draft)
==============================

Backward compatibility notes
----------------------------

 * The default value we give to the environment variable LESS has been
   changed from "FRSX" to "FRX", losing "S" (chop long lines instead
   of wrapping).  Existing users who prefer not to see line-wrapped
   output may want to set

     $ git config core.pager "less -S"

   to restore the traditional behaviour.  It is expected that people
   find output from most subcommands easier to read with the new
   default, except for "blame" which tends to produce really long
   lines.  To override the new default only for "git blame", you can
   do this:

     $ git config pager.blame "less -S"

 * A few disused directories in contrib/ have been retired.


Updates since v2.0
------------------

UI, Workflows & Features

 * Since the very beginning of Git, we gave the LESS environment a
   default value "FRSX" when we spawn "less" as the pager.  "S" (chop
   long lines instead of wrapping) has been removed from this default
   set of options, because it is more or less a personal taste thing,
   as opposed to the others that have good justifications (i.e. "R" is
   very much justified because many kinds of output we produce are
   colored and "FX" is justified because output we produce is often
   shorter than a page).

 * The logic and data used to compute the display width needed for
   UTF-8 strings have been updated to match Unicode 7.0 better.

 * HTTP-based transports learned to better propagate the error messages from
   the webserver to the client coming over the HTTP transport.

 * The completion script for bash (in contrib/) has been updated to
   better handle aliases that define a complex sequence of commands.

 * The "core.preloadindex" configuration variable is enabled by default,
   allowing modern platforms to take advantage of their
   multiple cores.

 * "git clone" applies the "if cloning from a local disk, physically
   copy the repository using hardlinks, unless otherwise told not to with
   --no-local" optimization when the url.*.insteadOf mechanism rewrites a
   remote-repository "git clone $URL" into a
   clone from a local disk.

 * "git commit --date=<date>" option learned more
   timestamp formats, including "--date=now".

 * The `core.commentChar` configuration variable is used to specify a
   custom comment character (other than the default "#") for
   the commit message editor.  This can be set to `auto` to attempt to
   choose a different character that does not conflict with any that
   already starts a line in the message being edited, for cases like
   "git commit --amend".

 * "git format-patch" learned --signature-file=<file> to add the contents
   of a file as a signature to the mail message it produces.

 * "git grep" learned the grep.fullname configuration variable to force
   "--full-name" to be the default.  This may cause regressions for
   scripted users who do not expect this new behaviour.

 * "git imap-send" learned to ask the credential helper for auth
   material.

 * "git log" and friends now understand the value "auto" for the
   "log.decorate" configuration variable to enable the "--decorate"
   option automatically when the output is sent to tty.

 * "git merge" without an argument, even when there is an upstream
   defined for the current branch, refused to run until
   merge.defaultToUpstream is set to true.  Flip the default of that
   configuration variable to true.

 * "git mergetool" learned to drive the vimdiff3 backend.

 * mergetool.prompt used to default to 'true', always asking "do you
   really want to run the tool on this path?".  The default has been
   changed to 'false'.  However, the prompt will still appear if
   mergetool used its autodetection system to guess which tool to use.
   Users who explicitly specify or configure a tool will no longer see
   the prompt by default.

   Strictly speaking, this is a backward incompatible change and
   users need to explicitly set the variable to 'true' if they want
   to be prompted to confirm running the tool on each path.

 * "git replace" learned the "--edit" subcommand to create a
   replacement by editing an existing object.

 * "git replace" learned a "--graft" option to rewrite the parents of a
   commit.

 * "git send-email" learned "--to-cover" and "--cc-cover" options, to
   tell it to copy To: and Cc: headers found in the first input file
   when emitting later input files.

 * "git svn" learned to cope with malformed timestamps with only one
   digit in the hour part, e.g. 2014-01-07T5:01:02.048176Z, emitted
   by some broken subversion server implementations.

 * "git tag" when editing the tag message shows the name of the tag
   being edited as a comment in the editor.

 * "git tag" learned to pay attention to "tag.sort" configuration, to
   be used as the default sort order when no --sort=<value> option
   is given.

 * A new "git verify-commit" command, to check GPG signatures in signed
   commits, in a way similar to "git verify-tag" is used to check
   signed tags, was added.


Performance, Internal Implementation, etc.

 * Build procedure for 'subtree' (in contrib/) has been cleaned up.

 * Support for the profile-feedback build, which has
   bit-rotted for quite a while, has been updated.

 * An experimental format to use two files (the base file and
   incremental changes relative to it) to represent the index has been
   introduced; this may reduce I/O cost of rewriting a large index
   when only small part of the working tree changes.

 * Effort to shrink the size of patches Windows folks maintain on top
   by upstreaming them continues.  More tests that are not applicable
   to the Windows environment are identified and either skipped or
   made more portable.

 * Eradication of "test $condition -a $condition" from our scripts
   continues.

 * The `core.deltabasecachelimit` used to default to 16 MiB , but this
   proved to be too small, and has been bumped to 96 MiB.

 * "git blame" has been optimized greatly by reorganising the data
   structure that is used to keep track of the work to be done.

 * "git diff" that compares 3-or-more trees (e.g. parents and the
   result of a merge) has been optimized.

 * The API to update/delete references are being converted to handle
   updates to multiple references in a transactional way.  As an
   example, "update-ref --stdin [-z]" has been updated to use this
   API.

 * skip_prefix() and strip_suffix() API functions are used a lot more
   widely throughout the codebase now.

 * Parts of the test scripts can be skipped by using a range notation,
   e.g. "sh t1234-test.sh --run='1-4 6 8-'" to omit test piece 5 and 7
   and run everything else.


Also contains various documentation updates and code clean-ups.


Fixes since v2.0
----------------

Unless otherwise noted, all the fixes since v2.0 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * We used to unconditionally disable the pager in the pager process
   we spawn to feed out output, but that prevented people who want to
   run "less" within "less" from doing so.
   (merge c0459ca je/pager-do-not-recurse later to maint).

 * Tools that read diagnostic output in our standard error stream do
   not want to see terminal control sequence (e.g. erase-to-eol).
   Detect them by checking if the standard error stream is connected
   to a tty.
   (merge 38de156 mn/sideband-no-ansi later to maint).

 * Mishandling of patterns in .gitignore that have trailing SPs quoted
   with backslashes (e.g. ones that end with "\ ") has been
   corrected.
   (merge 97c1364be6b pb/trim-trailing-spaces later to maint).

 * Reworded the error message given upon a failure to open an existing
   loose object file due to e.g. permission issues; it was reported as
   the object being corrupt, but that is not quite true.
   (merge d6c8a05 jk/report-fail-to-read-objects-better later to maint).

 * "git log -2master" is a common typo that shows two commits starting
   from whichever random branch that is not 'master' that happens to
   be checked out currently.
   (merge e3fa568 jc/revision-dash-count-parsing later to maint).

 * Code to avoid adding the same alternate object store twice was
   subtly broken for a long time, but nobody seems to have noticed.
   (merge 80b4785 rs/fix-alt-odb-path-comparison later to maint).
   (merge 539e750 ek/alt-odb-entry-fix later to maint).

 * The "%<(10,trunc)%s" pretty format specifier in the log family of
   commands is used to truncate the string to a given length (e.g. 10
   in the example) with padding to column-align the output, but did
   not take into account that number of bytes and number of display
   columns are different.
   (merge 7d50987 as/pretty-truncate later to maint).

 * "%G" (nothing after G) is an invalid pretty format specifier, but
   the parser did not notice it as garbage.
   (merge 958b2eb jk/pretty-G-format-fixes later to maint).

 * A handful of code paths had to read the commit object more than
   once when showing header fields that are usually not parsed.  The
   internal data structure to keep track of the contents of the commit
   object has been updated to reduce the need for this double-reading,
   and to allow the caller find the length of the object.
   (merge 218aa3a jk/commit-buffer-length later to maint).

 * The "mailmap.file" configuration option did not support tilde
   expansion (i.e. ~user/path and ~/path).
   (merge 9352fd5 ow/config-mailmap-pathname later to maint).

 * The completion scripts (in contrib/) did not know about quite a few
   options that are common between "git merge" and "git pull", and a
   couple of options unique to "git merge".
   (merge 8fee872 jk/complete-merge-pull later to maint).

 * The unix-domain socket used by the sample credential cache daemon
   tried to unlink an existing stale one at a wrong path, if the path
   to the socket was given as an overlong path that does not fit in
   the sun_path member of the sockaddr_un structure.
   (merge 2869b3e rs/fix-unlink-unix-socket later to maint).

 * An ancient rewrite passed a wrong pointer to a curl library
   function in a rarely used code path.
   (merge 479eaa8 ah/fix-http-push later to maint).

 * "--ignore-space-change" option of "git apply" ignored the spaces
   at the beginning of lines too aggressively, which is inconsistent
   with the option of the same name that "diff" and "git diff" have.
   (merge 14d3bb4 jc/apply-ignore-whitespace later to maint).

 * "git blame" miscounted the number of columns needed to show localized
   timestamps, resulting in a jaggy left-side-edge for the source code
   lines in its output.
   (merge dd75553 jx/blame-align-relative-time later to maint).

 * "git blame" assigned the blame to the copy in the working-tree if
   the repository is set to core.autocrlf=input and the file used CRLF
   line endings.
   (merge 4d4813a bc/blame-crlf-test later to maint).

 * "git clone -b brefs/tags/bar" would have mistakenly thought we were
   following a single tag, even though it was a name of the branch,
   because it incorrectly used strstr().
   (merge 60a5f5f jc/fix-clone-single-starting-at-a-tag later to maint).

 * "git commit --allow-empty-message -C $commit" did not work when the
   commit did not have any log message.
   (merge 076cbd6 jk/commit-C-pick-empty later to maint).

 * "git diff --find-copies-harder" sometimes pretended as if the mode
   bits have changed for paths that are marked with the assume-unchanged
   bit.
   (merge 5304810 jk/diff-files-assume-unchanged later to maint).

 * "filter-branch" left an empty single-parent commit that results when
   all parents of a merge commit get mapped to the same commit, even
   under "--prune-empty".
   (merge 79bc4ef cb/filter-branch-prune-empty-degenerate-merges later to maint).

 * "git format-patch" did not enforce the rule that the "--follow"
   option from the log/diff family of commands must be used with
   exactly one pathspec.
   (merge dd63f16 jk/diff-follow-must-take-one-pathspec later to maint).

 * "git gc --auto" was recently changed to run in the background to
   give control back early to the end-user sitting in front of the
   terminal, but it forgot that housekeeping involving reflogs should
   be done without other processes competing for accesses to the refs.
   (merge 62aad18 nd/daemonize-gc later to maint).

 * "git grep -O" to show the lines that hit in the pager did not work
   well with case insensitive search.  We now spawn "less" with its
   "-I" option when it is used as the pager (which is the default).
   (merge f7febbe sk/spawn-less-case-insensitively-from-grep-O-i later to maint).

 * We used to disable threaded "git index-pack" on platforms without
   thread-safe pread(); use a different workaround for such
   platforms to allow threaded "git index-pack".
   (merge 3953949 nd/index-pack-one-fd-per-thread later to maint).

 * The error reporting from "git index-pack" has been improved to
   distinguish missing objects from type errors.
   (merge 77583e7 jk/index-pack-report-missing later to maint).

 * "log --show-signature" incorrectly decided the color to paint a
   mergetag that was and was not correctly validated.
   (merge 42c55ce mg/fix-log-mergetag-color later to maint).

 * "log --show-signature" did not pay attention to the "--graph" option.
   (merge cf3983d zk/log-graph-showsig later to maint).

 * "git mailinfo" used to read beyond the ends of header strings while
   parsing an incoming e-mail message to extract the patch.
   (merge b1a013d rs/mailinfo-header-cmp later to maint).

 * On a case insensitive filesystem, merge-recursive incorrectly
   deleted the file that is to be renamed to a name that is the same
   except for case differences.
   (merge baa37bf dt/merge-recursive-case-insensitive later to maint).

 * Merging changes into a file that ends in an incomplete line made the
   last line into a complete one, even when the other branch did not
   change anything around the end of file.
   (merge ba31180 mk/merge-incomplete-files later to maint).

 * "git pack-objects" unnecessarily copied the previous contents when
   extending the hashtable, even though it will populate the table
   from scratch anyway.
   (merge fb79947 rs/pack-objects-no-unnecessary-realloc later to maint).

 * Recent updates to "git repack" started to duplicate objects that
   are in packfiles marked with the .keep flag into the new packfile by
   mistake.
   (merge d078d85 jk/repack-pack-keep-objects later to maint).

 * "git rerere forget" did not work well when merge.conflictstyle
   was set to a non-default value.
   (merge de3d8bb fc/rerere-conflict-style later to maint).

 * "git remote rm" and "git remote prune" can involve removing many
   refs at once, which is not a very efficient thing to do when very
   many refs exist in the packed-refs file.
   (merge e6bea66 jl/remote-rm-prune later to maint).

 * "git log --exclude=<glob> --all | git shortlog" worked as expected,
   but "git shortlog --exclude=<glob> --all", which is supposed to be
   identical to the above pipeline, was not accepted at the command
   line argument parser level.
   (merge eb07774 jc/shortlog-ref-exclude later to maint).

 * The autostash mode of "git rebase -i" did not restore the dirty
   working tree state if the user aborted the interactive rebase by
   emptying the insn sheet.
   (merge ddb5432 rr/rebase-autostash-fix later to maint).

 * "git rebase --fork-point" did not filter out patch-identical
   commits correctly.

 * During "git rebase --merge", a conflicted patch could not be
   skipped with "--skip" if the next one also conflicted.
   (merge 95104c7 bc/fix-rebase-merge-skip later to maint).

 * "git show -s" (i.e. show log message only) used to incorrectly emit
   an extra blank line after a merge commit.
   (merge ad2f725 mk/show-s-no-extra-blank-line-for-merges later to maint).

 * "git status", even though it is a read-only operation, tries to
   update the index with refreshed lstat(2) info to optimize future
   accesses to the working tree opportunistically, but this could
   race with a "read-write" operation that modifies the index while it
   is running.  Detect such a race and avoid overwriting the index.
   (merge 426ddee ym/fix-opportunistic-index-update-race later to maint).

 * "git status" (and "git commit") behaved as if changes in a modified
   submodule are not there if submodule.*.ignore configuration is set,
   which was misleading.  The configuration is only to unclutter diff
   output during the course of development, and not to hide
   changes in the "status" output to cause the users forget to commit
   them.
   (merge c215d3d jl/status-added-submodule-is-never-ignored later to maint).

 * Documentation for "git submodule sync" forgot to say that the subcommand
   can take the "--recursive" option.
   (merge 9393ae7 mc/doc-submodule-sync-recurse later to maint).

 * "git update-index --cacheinfo" in 2.0 release crashed on a
   malformed command line.
   (merge c8e1ee4 jc/rev-parse-argh-dashed-multi-words later to maint).

 * The mode to run tests with HTTP server tests disabled was broken.
   (merge afa53fe na/no-http-test-in-the-middle later to maint).

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

Changes since v2.1.0-rc1 are as follows:

Junio C Hamano (2):
      RelNotes: no more check_ref_format micro-optimization
      Git 2.1-rc2

Marc Branchaud (1):
      Release notes: grammatical fixes

Stefan Beller (1):
      various contrib: Fix links in man pages

^ permalink raw reply	[relevance 2%]

* Re: Unify subcommand structure; introduce double dashes for all subcommands?
  2014-07-23 17:52  2% ` Junio C Hamano
@ 2014-08-10 15:26  2%   ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2014-08-10 15:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: GIT Mailing-list

On 23.07.2014 19:52, Junio C Hamano wrote:
> Stefan Beller <stefanbeller@gmail.com> writes:
> 
>> A git command is generally setup as:
>> 	git <command> [<subcommand>] [<options>] ...
>>
>> The subcommands vary wildly by the nature of the command. However all
>> subcommands
>> could at least follow one style. The commands bundle, notes, stash and
>> submodule
>> have subcommands without two leading dashes (i.e. git stash list) as
>> opposed to all
>> other commands (i.e. git tag --list).
> 
> Sounds familiar.  E.g. here is a similar thread about a year ago.
> 
>   http://thread.gmane.org/gmane.comp.version-control.git/231376/focus=231478
> 
> Further discussions to make the plan more concrete is very much
> welcomed.
> 
> Thanks.
> 

So I'd want to add have the subcommands without double dashes ideally.
It's just less typing and more english like, not cryptic with dashes. 
This may come handy for newcomers/beginners using git. It also benefits 
the powerusers of git as you spare the typing of 2 dashes on the subcommand.

I'm currently trying to understand the functions to parse options 
and I wonder if the following is possible:

If there is an option set by OPT_CMDMODE 
(such as git tag --delete / --verify) we want to add an internal option,
(such as PARSE_OPT_NODASH ?), 
that you can deliver this CMD_MODE option without leading 2 dashes. 
The current behavior with leading 2 dashes is still supported, 
but maybe a warning is printed about deprecating the option with 2 dashes.

Having this change in place will switch over revert, replace, tag and merge-base
to having sane subcommands without dashes possible.

Once this change is in, we can rewrite the other commands, 
which as of now don't require the dashes.
Coincidentally these commands heavily rely on option parsing themselves,
such as git-notes having this code in place:

	if (argc < 1 || !strcmp(argv[0], "list"))
		result = list(argc, argv, prefix);
	else if (!strcmp(argv[0], "add"))
		result = add(argc, argv, prefix);
	else if (!strcmp(argv[0], "copy"))
		result = copy(argc, argv, prefix);
	...

Does that make sense?
Stefan

^ permalink raw reply	[relevance 2%]

* What's cooking in git.git (Oct 2014, #06; Fri, 24)
@ 2014-10-24 22:34  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-10-24 22:34 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[Graduated to "master"]

* da/mergetool-meld (2014-10-16) 1 commit
  (merged to 'next' on 2014-10-17 at 00ee553)
 + mergetools/meld: make usage of `--output` configurable and more robust

 Newer versions of 'meld' breaks the auto-detection we use to see if
 they are new enough to support the `--output` option.


* da/mergetool-temporary-directory (2014-10-16) 2 commits
  (merged to 'next' on 2014-10-17 at 261e74e)
 + t7610-mergetool: add test cases for mergetool.writeToTemp
 + mergetool: add an option for writing to a temporary directory
 (this branch uses da/mergetool-temporary-filename and da/mergetool-tests; is tangled with da/mergetool-tool-help.)

 Allow a temporary directory specified to be used while running "git
 mergetool" backend.


* da/mergetool-temporary-filename (2014-10-16) 1 commit
  (merged to 'next' on 2014-10-17 at 3fb95b5)
 + mergetool: use more conservative temporary filenames
 (this branch is used by da/mergetool-temporary-directory; uses da/mergetool-tests; is tangled with da/mergetool-tool-help.)

 Tweak the names of the three throw-away files "git mergetool" comes
 up with to feed the merge tool backend, so that a file with a
 single dot in its name in the original (e.g. "hello.c") will have
 only one dot in these variants (e.g. "hello_BASE_4321.c").


* da/mergetool-tests (2014-10-16) 4 commits
  (merged to 'next' on 2014-10-17 at 239fefe)
 + test-lib-functions: adjust style to match CodingGuidelines
 + t7610-mergetool: use test_config to isolate tests
 + t7610-mergetool: add missing && and remove commented-out code
 + t7610-mergetool: use tabs instead of a mix of tabs and spaces
 (this branch is used by da/mergetool-temporary-directory and da/mergetool-temporary-filename; is tangled with da/mergetool-tool-help.)

 The clean-up of this test script was long overdue and is a very
 welcome change.


* da/mergetool-tool-help (2014-10-15) 8 commits
  (merged to 'next' on 2014-10-17 at 854654c)
 + difftool: don't assume that default sh is sane
 + mergetool: don't require a work tree for --tool-help
 + git-sh-setup: move GIT_DIR initialization into a function
 + mergetool: use more conservative temporary filenames
 + test-lib-functions: adjust style to match CodingGuidelines
 + t7610-mergetool: prefer test_config over git config
 + t7610-mergetool: add missing && and remove commented-out code
 + t7610-mergetool: use tabs instead of a mix of tabs and spaces
 (this branch is tangled with da/mergetool-temporary-directory, da/mergetool-temporary-filename and da/mergetool-tests.)

 Allow "git mergetool --help" to run outside a Git repository.


* eb/no-pthreads (2014-10-19) 3 commits
  (merged to 'next' on 2014-10-21 at c455d39)
 + Handle atexit list internaly for unthreaded builds
 + pack-objects: set number of threads before checking and warning
 + index-pack: fix compilation with NO_PTHREADS

 Allow us build with NO_PTHREADS=NoThanks compilation option.  The
 last change (not queued) needs a bit more explanation in its log
 message.


* jk/pack-objects-no-bitmap-when-splitting (2014-10-19) 1 commit
  (merged to 'next' on 2014-10-21 at c3c8c2a)
 + pack-objects: turn off bitmaps when we split packs

 Splitting pack-objects output into multiple packs is incompatible
 with the use of reachability bitmap.


* js/completion-hide-not-a-repo (2014-10-14) 1 commit
  (merged to 'next' on 2014-10-17 at 466de3c)
 + completion: silence "fatal: Not a git repository" error

 Some internal error messages leaked out of the bash completion when
 typing "git cmd <TAB>" and the machinery tried to complete
 refnames.


* nd/dir-prep-exclude-cleanup (2014-10-21) 1 commit
  (merged to 'next' on 2014-10-21 at c90ba7a)
 + dir.c: remove the second declaration of "stk" in prep_exclude()

 Code clean-up.


* po/doc-status-markup (2014-10-19) 1 commit
  (merged to 'next' on 2014-10-21 at efca89c)
 + doc: fix 'git status --help' character quoting

 Update documentation mark-up.


* rs/ref-transaction (2014-10-15) 25 commits
  (merged to 'next' on 2014-10-17 at 1390624)
 + ref_transaction_commit: bail out on failure to remove a ref
 + lockfile: remove unable_to_lock_error
 + refs.c: do not permit err == NULL
 + remote rm/prune: print a message when writing packed-refs fails
 + for-each-ref: skip and warn about broken ref names
 + refs.c: allow listing and deleting badly named refs
 + test: put tests for handling of bad ref names in one place
 + packed-ref cache: forbid dot-components in refnames
 + branch -d: simplify by using RESOLVE_REF_READING
 + branch -d: avoid repeated symref resolution
 + reflog test: test interaction with detached HEAD
 + refs.c: change resolve_ref_unsafe reading argument to be a flags field
 + refs.c: make write_ref_sha1 static
 + fetch.c: change s_update_ref to use a ref transaction
 + refs.c: ref_transaction_commit: distinguish name conflicts from other errors
 + refs.c: pass a list of names to skip to is_refname_available
 + refs.c: call lock_ref_sha1_basic directly from commit
 + refs.c: refuse to lock badly named refs in lock_ref_sha1_basic
 + rename_ref: don't ask read_ref_full where the ref came from
 + refs.c: pass the ref log message to _create/delete/update instead of _commit
 + refs.c: add an err argument to delete_ref_loose
 + wrapper.c: add a new function unlink_or_msg
 + refs.c: lock_ref_sha1_basic is used for all refs
 + wrapper.c: remove/unlink_or_warn: simplify, treat ENOENT as success
 + mv test: recreate mod/ directory instead of relying on stale copy

 The API to update refs have been restructured to allow introducing
 a true transactional updates later.  We would even allow storing
 refs in backends other than the traditional filesystem-based one.


* rs/run-command-env-array (2014-10-19) 2 commits
  (merged to 'next' on 2014-10-21 at 4e56fa2)
 + use env_array member of struct child_process
 + run-command: add env_array, an optional argv_array for env

 Add managed "env" array to child_process to clarify the lifetime
 rules.


* sb/plug-transport-leak (2014-10-21) 2 commits
  (merged to 'next' on 2014-10-21 at 0a462d7)
 + .mailmap: add Stefan Bellers corporate mail address
 + transport: free leaking head in transport_print_push_status()

 Code clean-up.


* tb/core-filemode-doc (2014-10-19) 1 commit
  (merged to 'next' on 2014-10-21 at ad3e63b)
 + core.filemode may need manual action

 Doc update.


* wk/t1304-wo-USER (2014-10-19) 1 commit
  (merged to 'next' on 2014-10-21 at 00fe6d9)
 + t1304: Set LOGNAME even if USER is unset or null

--------------------------------------------------
[New Topics]

* zk/grep-color-words (2014-10-22) 1 commit
  (merged to 'next' on 2014-10-24 at 2d2f8f8)
 + grep: fix match highlighting for combined patterns with context lines

 "git grep --color" highlighted matching tokens on non-matching
 context lines and function name headers, which was unwanted.

 Will merge to 'master'.


* jc/conflict-hint (2014-10-24) 3 commits
 - merge & sequencer: turn "Conflicts:" hint into a comment
 - merge & sequencer: unify codepaths that write "Conflicts:" hint
 - builtin/merge.c: drop a parameter that is never used


* jc/diff-b-m (2014-10-23) 1 commit
 - diff -B -M: fix output for "copy and then rewrite" case


* oc/mergetools-beyondcompare (2014-10-21) 1 commit
  (merged to 'next' on 2014-10-24 at e9278e8)
 + mergetool: rename bc3 to bc

 Will merge to 'master'.


* rs/ref-transaction-reflog (2014-10-22) 15 commits
 - refs.c: allow deleting refs with a broken sha1
 - refs.c: remove lock_any_ref_for_update
 - refs.c: make unlock_ref/close_ref/commit_ref static
 - refs.c: rename log_ref_setup to create_reflog
 - reflog.c: use a reflog transaction when writing during expire
 - refs.c: allow multiple reflog updates during a single transaction
 - refs.c: only write reflog update if msg is non-NULL
 - refs.c: add a flag to allow reflog updates to truncate the log
 - refs.c: add a transaction function to append a reflog entry
 - copy.c: make copy_fd preserve meaningful errno
 - refs.c: add a function to append a reflog entry to a fd
 - refs.c: add a new update_type field to ref_update
 - refs.c: rename the transaction functions
 - refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 - refs.c make ref_transaction_create a wrapper to ref_transaction_update
 (this branch is used by rs/ref-transaction-rename and rs/ref-transaction-send-pack.)


* rs/ref-transaction-rename (2014-10-22) 15 commits
 - refs.c: add an err argument to pack_refs
 - refs.c: make lock_packed_refs take an err argument
 - refs.c: make add_packed_ref return an error instead of calling die
 - refs.c: replace the onerr argument in update_ref with a strbuf err
 - refs.c: make the *_packed_refs functions static
 - refs.c: make repack_without_refs static
 - remote.c: use a transaction for deleting refs
 - refs.c: write updates to packed refs when a transaction has more than one ref
 - refs.c: move reflog updates into its own function
 - refs.c: rollback the lockfile before we die() in repack_without_refs
 - refs.c: update rename_ref to use a transaction
 - refs.c: use a stringlist for repack_without_refs
 - refs.c: use packed refs when deleting refs during a transaction
 - refs.c: return error instead of dying when locking fails during transaction
 - refs.c: allow passing raw git_committer_info as email to _update_reflog
 (this branch is used by rs/ref-transaction-send-pack; uses rs/ref-transaction-reflog.)


* rs/ref-transaction-send-pack (2014-10-22) 8 commits
 - refs.c: add an err argument to create_symref
 - refs.c: add an err argument to create_reflog
 - receive-pack.c: add a receive.preferatomicpush configuration variable
 - t5543-atomic-push.sh: add basic tests for atomic pushes
 - push.c: add an --atomic-push argument
 - receive-pack.c: use a single transaction when atomic-push is negotiated
 - send-pack.c: add an --atomic-push command line argument
 - receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses rs/ref-transaction-reflog and rs/ref-transaction-rename.)

--------------------------------------------------
[Stalled]

* je/quiltimport-no-fuzz (2014-10-21) 2 commits
 - git-quiltimport: flip the default not to allow fuzz
 - git-quiltimport.sh: allow declining fuzz with --exact option

 "quiltimport" drove "git apply" always with -C1 option to reduce
 context of the patch in order to give more chance to somewhat stale
 patches to apply.  Add an "--exact" option to disable, and also
 "-C$n" option to customize this behaviour.  The top patch
 optionally flips the default to "--exact".

 Waiting for an Ack.


* jc/push-cert-hmac-optim (2014-09-25) 2 commits
 - receive-pack: truncate hmac early and convert only necessary bytes
 - sha1_to_hex: split out "hex-format n bytes" helper and use it

 This is "we could do this if we wanted to", not "we measured and it
 improves performance critical codepath".

 Will perhaps drop.


* nd/multiple-work-trees (2014-09-27) 32 commits
 . t2025: add a test to make sure grafts is working from a linked checkout
 . checkout: don't require a work tree when checking out into a new one
 . git_path(): keep "info/sparse-checkout" per work-tree
 . count-objects: report unused files in $GIT_DIR/worktrees/...
 . gc: support prune --worktrees
 . gc: factor out gc.pruneexpire parsing code
 . gc: style change -- no SP before closing parenthesis
 . checkout: clean up half-prepared directories in --to mode
 . checkout: reject if the branch is already checked out elsewhere
 . prune: strategies for linked checkouts
 . checkout: support checking out into a new working directory
 . use new wrapper write_file() for simple file writing
 . wrapper.c: wrapper to open a file, fprintf then close
 . setup.c: support multi-checkout repo setup
 . setup.c: detect $GIT_COMMON_DIR check_repository_format_gently()
 . setup.c: convert check_repository_format_gently to use strbuf
 . setup.c: detect $GIT_COMMON_DIR in is_git_directory()
 . setup.c: convert is_git_directory() to use strbuf
 . git-stash: avoid hardcoding $GIT_DIR/logs/....
 . *.sh: avoid hardcoding $GIT_DIR/hooks/...
 . git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects
 . $GIT_COMMON_DIR: a new environment variable
 . commit: use SEQ_DIR instead of hardcoding "sequencer"
 . fast-import: use git_path() for accessing .git dir instead of get_git_dir()
 . reflog: avoid constructing .lock path with git_path
 . *.sh: respect $GIT_INDEX_FILE
 . git_path(): be aware of file relocation in $GIT_DIR
 . path.c: group git_path(), git_pathdup() and strbuf_git_path() together
 . path.c: rename vsnpath() to do_git_path()
 . git_snpath(): retire and replace with strbuf_git_path()
 . path.c: make get_pathname() call sites return const char *
 . path.c: make get_pathname() return strbuf instead of static buffer

 A replacement for contrib/workdir/git-new-workdir that does not
 rely on symbolic links and make sharing of objects and refs safer
 by making the borrowee and borrowers aware of each other.

 A few tests need some tweaks for MinGW ($gmane/{257756,257757}).
 Conflicts with rs/ref-transaction so ejected for now, waiting for a
 reroll.


* mt/patch-id-stable (2014-06-10) 1 commit
 - patch-id: change default to stable

 Teaches "git patch-id" to compute the patch ID that does not change
 when the files in a single patch is reordered. As this new algorithm
 is backward incompatible, the last bit to flip it to be the default
 is left out of 'master' for now.

 Nobody seems to be jumping up & down requesting this last step,
 which makes the result somewhat backward incompatible.
 Will perhaps drop.


* tr/remerge-diff (2014-09-08) 8 commits
 - log --remerge-diff: show what the conflict resolution changed
 - name-hash: allow dir hashing even when !ignore_case
 - merge-recursive: allow storing conflict hunks in index
 - merge_diff_mode: fold all merge diff variants into an enum
 - combine-diff: do not pass revs->dense_combined_merges redundantly
 - merge-recursive: -Xindex-only to leave worktree unchanged
 - merge-recursive: internal flag to avoid touching the worktree
 - merge-recursive: remove dead conditional in update_stages()

 "log -p" output learns a new way to let users inspect a merge
 commit by showing the differences between the automerged result
 with conflicts the person who recorded the merge would have seen
 and the final conflict resolution that was recorded in the merge.

 Waiting for a reroll ($gmane/256591).


* hv/submodule-config (2014-06-30) 4 commits
 - do not die on error of parsing fetchrecursesubmodules option
 - use new config API for worktree configurations of submodules
 - extract functions for submodule config set and lookup
 - implement submodule config cache for lookup of submodule names

 Kicked back to 'pu' per request ($gmane/255610).


* jt/timer-settime (2014-08-29) 6 commits
 - use timer_settime() for new platforms
 - autoconf: check for timer_settime()
 - autoconf: check for struct itimerspec
 - autoconf: check for struct sigevent
 - autoconf: check for struct timespec
 - autoconf: check for timer_t

 Reviewed, discussed and wanting for a reroll.


* jk/pack-bitmap (2014-08-04) 1 commit
 - pack-bitmap: do not use gcc packed attribute

 Hold, waiting for Karsten's replacement.


* ab/add-interactive-show-diff-func-name (2014-05-12) 2 commits
 - SQUASH??? git-add--interactive: Preserve diff heading when splitting hunks
 - git-add--interactive: Preserve diff heading when splitting hunks

 Waiting for a reroll.


* jn/gitweb-utf8-in-links (2014-05-27) 1 commit
 - gitweb: Harden UTF-8 handling in generated links

 $gmane/250758?


* ss/userdiff-update-csharp-java (2014-06-02) 2 commits
 - userdiff: support Java try keyword
 - userdiff: support C# async methods and correct C# keywords

 Reviews sent; waiting for a response.


* bg/rebase-off-of-previous-branch (2014-04-16) 1 commit
 - git-rebase: print name of rev when using shorthand

 Teach "git rebase -" to report the concrete name of the branch
 (i.e. the previous one).

 But it stops short and does not do the same for "git rebase @{-1}".
 Expecting a reroll.


* rb/merge-prepare-commit-msg-hook (2014-01-10) 4 commits
 - merge: drop unused arg from abort_commit method signature
 - merge: make prepare_to_commit responsible for write_merge_state
 - t7505: ensure cleanup after hook blocks merge
 - t7505: add missing &&

 Expose more merge states (e.g. $GIT_DIR/MERGE_MODE) to hooks that
 run during "git merge".  The log message stresses too much on one
 hook, prepare-commit-msg, but it would equally apply to other hooks
 like post-merge, I think.

 Waiting for a reroll.


* jc/graph-post-root-gap (2013-12-30) 3 commits
 - WIP: document what we want at the end
 - graph: remove unused code a bit
 - graph: stuff the current commit into graph->columns[]

 This was primarily a RFH ($gmane/239580).


* tg/perf-lib-test-perf-cleanup (2013-09-19) 2 commits
 - perf-lib: add test_perf_cleanup target
 - perf-lib: split starting the test from the execution

 Add test_perf_cleanup shell function to the perf suite, that allows
 the script writers to define a test with a clean-up action.

 Will hold.


* jc/show-branch (2014-03-24) 5 commits
 - show-branch: use commit slab to represent bitflags of arbitrary width
 - show-branch.c: remove "all_mask"
 - show-branch.c: abstract out "flags" operation
 - show-branch.c: lift all_mask/all_revs to a global static
 - show-branch.c: update comment style

 Waiting for the final step to lift the hard-limit before sending it out.

--------------------------------------------------
[Cooking]

* bc/asciidoctor (2014-10-15) 2 commits
  (merged to 'next' on 2014-10-17 at 12ce2e2)
 + Documentation: implement linkgit macro for Asciidoctor
 + Documentation: move some AsciiDoc parameters into variables

 Add machinery to alternatively use AsciiDoctor to format our
 documentation.

 Brian seems to have a bit more tweaks; will wait for them before
 moving this topic forward.


* jk/prune-mtime (2014-10-19) 28 commits
  (merged to 'next' on 2014-10-20 at fdd7ff6)
 + drop add_object_array_with_mode
 + revision: remove definition of unused 'add_object' function
 + pack-objects: double-check options before discarding objects
 + repack: pack objects mentioned by the index
 + pack-objects: use argv_array
 + reachable: use revision machinery's --indexed-objects code
 + rev-list: add --indexed-objects option
 + rev-list: document --reflog option
 + t5516: test pushing a tag of an otherwise unreferenced blob
 + traverse_commit_list: support pending blobs/trees with paths
 + make add_object_array_with_context interface more sane
 + write_sha1_file: freshen existing objects
 + pack-objects: match prune logic for discarding objects
 + pack-objects: refactor unpack-unreachable expiration check
 + prune: keep objects reachable from recent objects
 + sha1_file: add for_each iterators for loose and packed objects
 + count-objects: use for_each_loose_file_in_objdir
 + count-objects: do not use xsize_t when counting object size
 + prune-packed: use for_each_loose_file_in_objdir
 + reachable: mark index blobs as SEEN
 + prune: factor out loose-object directory traversal
 + reachable: reuse revision.c "add all reflogs" code
 + reachable: use traverse_commit_list instead of custom walk
 + clean up name allocation in prepare_revision_walk
 + object_array: add a "clear" function
 + object_array: factor out slopbuf-freeing logic
 + isxdigit: cast input to unsigned char
 + foreach_alt_odb: propagate return value from callback

 Tighten the logic to decide that an unreachable cruft is
 sufficiently old by covering corner cases such as an ancient object
 becoming reachable and then going unreachable again, in which case
 its retention period should be prolonged.

 Will merge to 'master'.


* jc/checkout-local-track-report (2014-10-14) 1 commit
  (merged to 'next' on 2014-10-21 at f636a00)
 + checkout: report upstream correctly even with loosely defined branch.*.merge

 The report from "git checkout" on a branch that builds on another
 local branch by setting its branch.*.merge to branch name (not a
 full refname) incorrectly said that the upstream is gone.


* jc/clone-borrow (2014-10-15) 1 commit
  (merged to 'next' on 2014-10-21 at b76ea34)
 + clone: --dissociate option to mark that reference is only temporary

 Allow "git clone --reference" to be used more safely.

--------------------------------------------------
[Discarded]

* jk/tag-contains (2014-06-30) 8 commits
 . perf: add tests for tag --contains
 . tag: use commit_contains
 . commit: provide a fast multi-tip contains function
 . string-list: add pos to iterator callback
 . add functions for memory-efficient bitmaps
 . paint_down_to_common: use prio_queue
 . tag: factor out decision to stream tags
 . tag: allow --sort with -n

 Expecting a reroll.


* jk/makefile (2014-02-05) 16 commits
 . FIXUP
 . move LESS/LV pager environment to Makefile
 . Makefile: teach scripts to include make variables
 . FIXUP
 . Makefile: auto-build C strings from make variables
 . Makefile: drop *_SQ variables
 . FIXUP
 . Makefile: add c-quote helper function
 . Makefile: introduce sq function for shell-quoting
 . Makefile: always create files via make-var
 . Makefile: store GIT-* sentinel files in MAKE/
 . Makefile: prefer printf to echo for GIT-*
 . Makefile: use tempfile/mv strategy for GIT-*
 . Makefile: introduce make-var helper function
 . Makefile: fix git-instaweb dependency on gitweb
 . Makefile: drop USE_GETTEXT_SCHEME from GIT-CFLAGS

 Simplify the Makefile rules and macros that exist primarily for
 quoting purposes, and make it easier to robustly express the
 dependency rules.

 Expecting a reroll.

^ permalink raw reply	[relevance 2%]

* What's cooking in git.git (Nov 2014, #04; Wed, 26)
@ 2014-11-26 23:09  3% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-11-26 23:09 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

I haven't had time to write comments (they are essentially release
notes entries to be used when/if the topic graduates to 'master')
for new topics, but I am pushing this out to show the current state
of affairs.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[Graduated to "master"]

* cc/interpret-trailers (2014-11-10) 2 commits
  (merged to 'next' on 2014-11-14 at fa0ccc6)
 + trailer: display a trailer without its trailing newline
 + trailer: ignore comment lines inside the trailers
 (this branch is used by cc/interpret-trailers-more.)

 Small fixes to a new experimental command already in 'master'.


* da/difftool (2014-11-14) 1 commit
  (merged to 'next' on 2014-11-17 at 231f559)
 + difftool: honor --trust-exit-code for builtin tools

 Fix-up to a new feature in 'master'.


* jc/doc-commit-only (2014-11-07) 1 commit
  (merged to 'next' on 2014-11-14 at 29c70d2)
 + Documentation/git-commit: clarify that --only/--include records the working tree contents


* mh/doc-remote-helper-xref (2014-11-11) 1 commit
  (merged to 'next' on 2014-11-14 at a7f6230)
 + doc: add some crossrefs between manual pages


* sn/tutorial-status-output-example (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at 0fe4930)
 + gittutorial: fix output of 'git status'


* sv/submitting-final-patch (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at 9e1220f)
 + SubmittingPatches: final submission is To: maintainer and CC: list


* ta/tutorial-modernize (2014-11-11) 1 commit
  (merged to 'next' on 2014-11-14 at c45f0ac)
 + gittutorial.txt: remove reference to ancient Git version


* tb/no-relative-file-url (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at 96e9227)
 + t5705: the file:// URL should be absolute

--------------------------------------------------
[New Topics]

* jc/unpack-trees-plug-leak (2014-11-17) 1 commit
 - unpack_trees: plug leakage of o->result


* js/windows-open-eisdir-error (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at 57b0d49)
 + Windows: correct detection of EISDIR in mingw_open()


* rs/maint-config-use-labs (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at 53c2404)
 + use labs() for variables of type long instead of abs()


* rs/receive-pack-use-labs (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at c6d2d94)
 + use labs() for variables of type long instead of abs()


* jk/colors (2014-11-20) 5 commits
 - diff-highlight: allow configurable colors
 - parse_color: recognize "no$foo" to clear the $foo attribute
 - parse_color: support 24-bit RGB values
 - parse_color: refactor color storage
 - Merge branch 'jn/parse-config-slot' into jk/colors
 (this branch uses jk/colors-fix.)


* jk/colors-fix (2014-11-20) 3 commits
 - t4026: test "normal" color
 - config: fix parsing of "git config --get-color some.key -1"
 - docs: describe ANSI 256-color mode
 (this branch is used by jk/colors.)


* jk/gitweb-with-newer-cgi-multi-param (2014-11-18) 1 commit
  (merged to 'next' on 2014-11-18 at 6ac61fe)
 + gitweb: hack around CGI's list-context param() handling


* jk/lock-ref-sha1-basic-return-errors (2014-11-20) 1 commit
 - lock_ref_sha1_basic: do not die on locking errors


* jk/no-perl-tests (2014-11-18) 2 commits
 - t960[34]: mark cvsimport tests as requiring perl
 - t0090: mark add-interactive test with PERL prerequisite


* jk/rebuild-perl-scripts-with-no-perl-seting-change (2014-11-18) 3 commits
 - Makefile: have python scripts depend on NO_PYTHON setting
 - Makefile: simplify by using SCRIPT_{PERL,SH}_GEN macros
 - Makefile: have perl scripts depend on NO_PERL setting


* mh/config-copy-string-from-git-path (2014-11-17) 1 commit
 - cmd_config(): make a copy of path obtained from git_path()


* mh/config-flip-xbit-back-after-checking (2014-11-18) 1 commit
  (merged to 'next' on 2014-11-18 at 45f7d71)
 + create_default_files(): don't set u+x bit on $GIT_DIR/config
 (this branch is used by tb/config-core-filemode-check-on-broken-fs.)


* po/everyday-doc (2014-11-17) 1 commit
 - Documentation: change "gitlink" typo in git-push


* ps/new-workdir-into-empty-directory (2014-11-20) 1 commit
 - git-new-workdir: Don't fail if the target directory is empty


* rt/push-recurse-submodule-usage-string (2014-11-18) 1 commit
 - builtin/push.c: fix description of --recurse-submodules option


* sb/copy-fd-errno (2014-11-17) 1 commit
 - copy.c: make copy_fd preserve meaningful errno


* sb/log-ref-write-fd (2014-11-20) 1 commit
 - refs.c: add a function to append a reflog entry to a fd


* sb/ref-transaction-unify-to-update (2014-11-20) 2 commits
 - refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 - refs.c: make ref_transaction_create a wrapper for ref_transaction_update


* sv/doc-stripspace (2014-11-19) 1 commit
 - Documentation/git-stripspace: Update synopsis


* sv/typofix-apply-error-message (2014-11-17) 1 commit
 - apply: fix typo in an error message


* da/difftool-mergetool-simplify-reporting-status (2014-11-21) 5 commits
 - mergetools: stop setting $status in merge_cmd()
 - mergetool: simplify conditionals
 - difftool--helper: add explicit exit statement
 - mergetool--lib: remove use of $status global
 - mergetool--lib: remove no-op assignment to $status from setup_user_tool


* dw/shell-basename-dashdash-before-stripping-leading-dash-from-login (2014-11-25) 1 commit
 - git-sh-setup.sh: use dashdash with basename call


* jc/refer-to-t-readme-from-submitting-patches (2014-11-24) 2 commits
 - t/README: justify why "! grep foo" is sufficient
 - SubmittingPatches: refer to t/README for tests


* jc/t9001-modernise (2014-11-25) 5 commits
 - t9001: style modernisation phase #5
 - t9001: style modernisation phase #4
 - t9001: style modernisation phase #3
 - t9001: style modernisation phase #2
 - t9001: style modernisation phase #1
 (this branch uses pb/send-email-te.)


* js/t5000-dont-copy-bin-sh (2014-11-24) 1 commit
 - t5000 on Windows: do not mistake "sh.exe" as "sh"


* mg/add-ignore-errors (2014-11-21) 1 commit
 - add: ignore only ignored files


* mh/find-uniq-abbrev (2014-11-26) 1 commit
 - sha1_name: avoid unnecessary sha1 lookup in find_unique_abbrev


* mh/simplify-repack-without-refs (2014-11-25) 7 commits
 - sort_string_list(): rename to string_list_sort()
 - prune_remote(): iterate using for_each_string_list_item()
 - prune_remote(): rename local variable
 - repack_without_refs(): make the refnames argument a string_list
 - prune_remote(): sort delete_refs_list references en masse
 - prune_remote(): initialize both delete_refs lists in a single loop
 - prune_remote(): exit early if there are no stale references


* pb/am-message-id-footer (2014-11-25) 2 commits
 - git-am: add --message-id/--no-message-id
 - git-mailinfo: add --message-id


* pb/send-email-te (2014-11-25) 2 commits
 - git-send-email: add --transfer-encoding option
 - git-send-email: delay creation of MIME headers
 (this branch is used by jc/t9001-modernise.)


* pw/remote-set-url-fetch (2014-11-26) 1 commit
 - remote: add --fetch and --both options to set-url


* rj/no-xopen-source-for-cygwin (2014-11-24) 1 commit
 - git-compat-util.h: don't define _XOPEN_SOURCE on cygwin


* sb/string-list (2014-11-25) 3 commits
 - string_list: remove string_list_insert_at_index() from its API
 - mailmap: use higher level string list functions
 - string_list: document string_list_(insert,lookup)


* sb/write-sha1-update-reflog (2014-11-24) 1 commit
 - refs.c: move reflog updates into its own function


* tb/config-core-filemode-check-on-broken-fs (2014-11-21) 1 commit
 - init-db: improve the filemode trustability check
 (this branch uses mh/config-flip-xbit-back-after-checking.)

--------------------------------------------------
[Stalled]

* je/quiltimport-no-fuzz (2014-10-21) 2 commits
 - git-quiltimport: flip the default not to allow fuzz
 - git-quiltimport.sh: allow declining fuzz with --exact option

 "quiltimport" drove "git apply" always with -C1 option to reduce
 context of the patch in order to give more chance to somewhat stale
 patches to apply.  Add an "--exact" option to disable, and also
 "-C$n" option to customize this behaviour.  The top patch
 optionally flips the default to "--exact".

 Waiting for an Ack.


* jc/push-cert-hmac-optim (2014-09-25) 2 commits
 - receive-pack: truncate hmac early and convert only necessary bytes
 - sha1_to_hex: split out "hex-format n bytes" helper and use it

 This is "we could do this if we wanted to", not "we measured and it
 improves performance critical codepath".

 Will perhaps drop.


* nd/multiple-work-trees (2014-09-27) 32 commits
 . t2025: add a test to make sure grafts is working from a linked checkout
 . checkout: don't require a work tree when checking out into a new one
 . git_path(): keep "info/sparse-checkout" per work-tree
 . count-objects: report unused files in $GIT_DIR/worktrees/...
 . gc: support prune --worktrees
 . gc: factor out gc.pruneexpire parsing code
 . gc: style change -- no SP before closing parenthesis
 . checkout: clean up half-prepared directories in --to mode
 . checkout: reject if the branch is already checked out elsewhere
 . prune: strategies for linked checkouts
 . checkout: support checking out into a new working directory
 . use new wrapper write_file() for simple file writing
 . wrapper.c: wrapper to open a file, fprintf then close
 . setup.c: support multi-checkout repo setup
 . setup.c: detect $GIT_COMMON_DIR check_repository_format_gently()
 . setup.c: convert check_repository_format_gently to use strbuf
 . setup.c: detect $GIT_COMMON_DIR in is_git_directory()
 . setup.c: convert is_git_directory() to use strbuf
 . git-stash: avoid hardcoding $GIT_DIR/logs/....
 . *.sh: avoid hardcoding $GIT_DIR/hooks/...
 . git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects
 . $GIT_COMMON_DIR: a new environment variable
 . commit: use SEQ_DIR instead of hardcoding "sequencer"
 . fast-import: use git_path() for accessing .git dir instead of get_git_dir()
 . reflog: avoid constructing .lock path with git_path
 . *.sh: respect $GIT_INDEX_FILE
 . git_path(): be aware of file relocation in $GIT_DIR
 . path.c: group git_path(), git_pathdup() and strbuf_git_path() together
 . path.c: rename vsnpath() to do_git_path()
 . git_snpath(): retire and replace with strbuf_git_path()
 . path.c: make get_pathname() call sites return const char *
 . path.c: make get_pathname() return strbuf instead of static buffer

 A replacement for contrib/workdir/git-new-workdir that does not
 rely on symbolic links and make sharing of objects and refs safer
 by making the borrowee and borrowers aware of each other.

 A few tests need some tweaks for MinGW ($gmane/{257756,257757}).
 Conflicts with rs/ref-transaction so ejected for now, waiting for a
 reroll.


* mt/patch-id-stable (2014-06-10) 1 commit
 - patch-id: change default to stable

 Teaches "git patch-id" to compute the patch ID that does not change
 when the files in a single patch is reordered. As this new algorithm
 is backward incompatible, the last bit to flip it to be the default
 is left out of 'master' for now.

 Nobody seems to be jumping up & down requesting this last step,
 which makes the result somewhat backward incompatible.
 Will perhaps drop.


* tr/remerge-diff (2014-11-10) 9 commits
 - t4213: avoid "|" in sed regexp
 - log --remerge-diff: show what the conflict resolution changed
 - name-hash: allow dir hashing even when !ignore_case
 - merge-recursive: allow storing conflict hunks in index
 - merge_diff_mode: fold all merge diff variants into an enum
 - combine-diff: do not pass revs->dense_combined_merges redundantly
 - merge-recursive: -Xindex-only to leave worktree unchanged
 - merge-recursive: internal flag to avoid touching the worktree
 - merge-recursive: remove dead conditional in update_stages()

 "log -p" output learns a new way to let users inspect a merge
 commit by showing the differences between the automerged result
 with conflicts the person who recorded the merge would have seen
 and the final conflict resolution that was recorded in the merge.

 Waiting for a reroll ($gmane/256591).


* hv/submodule-config (2014-11-11) 4 commits
 - do not die on error of parsing fetchrecursesubmodules option
 - use new config API for worktree configurations of submodules
 - extract functions for submodule config set and lookup
 - implement submodule config cache for lookup of submodule names

 Kicked back to 'pu' per request ($gmane/255610).


* jk/pack-bitmap (2014-08-04) 1 commit
 - pack-bitmap: do not use gcc packed attribute

 Hold, waiting for Karsten's replacement.


* ab/add-interactive-show-diff-func-name (2014-05-12) 2 commits
 - SQUASH??? git-add--interactive: Preserve diff heading when splitting hunks
 - git-add--interactive: Preserve diff heading when splitting hunks

 Waiting for a reroll.


* jn/gitweb-utf8-in-links (2014-05-27) 1 commit
 - gitweb: Harden UTF-8 handling in generated links

 $gmane/250758?


* ss/userdiff-update-csharp-java (2014-06-02) 2 commits
 - userdiff: support Java try keyword
 - userdiff: support C# async methods and correct C# keywords

 Reviews sent; waiting for a response.


* bg/rebase-off-of-previous-branch (2014-04-16) 1 commit
 - git-rebase: print name of rev when using shorthand

 Teach "git rebase -" to report the concrete name of the branch
 (i.e. the previous one).

 But it stops short and does not do the same for "git rebase @{-1}".
 Expecting a reroll.


* rb/merge-prepare-commit-msg-hook (2014-01-10) 4 commits
 - merge: drop unused arg from abort_commit method signature
 - merge: make prepare_to_commit responsible for write_merge_state
 - t7505: ensure cleanup after hook blocks merge
 - t7505: add missing &&

 Expose more merge states (e.g. $GIT_DIR/MERGE_MODE) to hooks that
 run during "git merge".  The log message stresses too much on one
 hook, prepare-commit-msg, but it would equally apply to other hooks
 like post-merge, I think.

 Waiting for a reroll.


* jc/graph-post-root-gap (2013-12-30) 3 commits
 - WIP: document what we want at the end
 - graph: remove unused code a bit
 - graph: stuff the current commit into graph->columns[]

 This was primarily a RFH ($gmane/239580).


* tg/perf-lib-test-perf-cleanup (2013-09-19) 2 commits
 - perf-lib: add test_perf_cleanup target
 - perf-lib: split starting the test from the execution

 Add test_perf_cleanup shell function to the perf suite, that allows
 the script writers to define a test with a clean-up action.

 Will hold.


* jc/show-branch (2014-03-24) 5 commits
 - show-branch: use commit slab to represent bitflags of arbitrary width
 - show-branch.c: remove "all_mask"
 - show-branch.c: abstract out "flags" operation
 - show-branch.c: lift all_mask/all_revs to a global static
 - show-branch.c: update comment style

 Waiting for the final step to lift the hard-limit before sending it out.

--------------------------------------------------
[Cooking]

* jk/approxidate-avoid-y-d-m-over-future-dates (2014-11-13) 2 commits
  (merged to 'next' on 2014-11-14 at 3c11a1b)
 + approxidate: allow ISO-like dates far in the future
 + pass TIME_DATE_NOW to approxidate future-check

 Traditionally we tried to avoid interpreting date strings given by
 the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
 used early November 2014 was taken as "October 12, 2014" because it
 is likely that a date in the future, December 10, is a mistake.

 Loosen this and do not tiebreak by future-ness of the date when

 (1) ISO-like format is used, and
 (2) the string can make sense interpreted as both y-m-d and y-d-m.

 Will cook in 'next' throughout the remainder of the cycle.


* jk/checkout-from-tree (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at ddbffb0)
 + checkout $tree: do not throw away unchanged index entries

 Will merge to 'master'.


* mb/enable-lib-terminal-test-on-newer-darwin (2014-11-14) 1 commit
  (merged to 'next' on 2014-11-14 at b2aae27)
 + t/lib-terminal: allow TTY tests to run under recent Mac OS

 Will cook in 'next' throughout the remainder of the cycle.

 We probably should drop this, though. ($gmane/259609).


* sv/get-builtin (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at 9497e17)
 + builtin: move builtin retrieval to get_builtin()

 Will merge to 'master'.


* br/imap-send-verbosity (2014-11-05) 1 commit
  (merged to 'next' on 2014-11-12 at d9e58ec)
 + imap-send: use parse options API to determine verbosity
 (this branch is used by br/imap-send-via-libcurl.)

 Will cook in 'next' throughout the remainder of the cycle.


* br/imap-send-via-libcurl (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-12 at 5327ab4)
 + git-imap-send: use libcurl for implementation
 (this branch uses br/imap-send-verbosity.)

 Will cook in 'next' throughout the remainder of the cycle.


* cc/interpret-trailers-more (2014-11-10) 4 commits
 - trailer: add test with an old style conflict block
 - trailer: reuse ignore_non_trailer() to ignore conflict lines
 - commit: make ignore_non_trailer() non static
 - Merge branch 'jc/conflict-hint' into cc/interpret-trailers-more
 (this branch uses jc/conflict-hint.)


* js/push-to-update (2014-11-13) 1 commit
 - Add another option for receive.denyCurrentBranch

 Still being discussed but we seem to have agreed what the desired
 semantics should be.


* rs/env-array-in-child-process (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-14 at 3f6ba07)
 + use args member of struct child_process

 Will merge to 'master'.


* tq/git-ssh-command (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-14 at 83f5dae)
 + git_connect: set ssh shell command in GIT_SSH_COMMAND

 Allow passing extra set of arguments when ssh is invoked to create
 an encrypted & authenticated connection, which is not possible with
 existing GIT_SSH mechanism, which was designed more to match what
 other programs with similar variables did, not necessarily to be
 more useful.

 Will merge to 'master'.


* ms/submodule-update-config-doc (2014-11-03) 1 commit
 - submodule: clarify documentation for update subcommand

 Needs a reroll ($gmane/259037).


* nd/lockfile-absolute (2014-11-03) 1 commit
  (merged to 'next' on 2014-11-06 at 68722a9)
 + lockfile.c: store absolute path

 The lockfile API can get confused which file to clean up when the
 process moved the $cwd after creating a lockfile.

 Will cook in 'next' throughout the remainder of the cycle.


* jh/empty-notes (2014-11-14) 9 commits
  (merged to 'next' on 2014-11-18 at 9eeb338)
 + t3301: modernize style
 + notes: empty notes should be shown by 'git log'
 + builtin/notes: add --allow-empty, to allow storing empty notes
 + builtin/notes: split create_note() to clarify add vs. remove logic
 + builtin/notes: simplify early exit code in add()
 + builtin/notes: refactor note file path into struct note_data
 + builtin/notes: improve naming
 + t3301: verify that 'git notes' removes empty notes by default
 + builtin/notes: fix premature failure when trying to add the empty blob

 A request to store an empty note via "git notes" meant to remove
 note from the object but with --allow-empty we will store a (surprise!)
 note that is empty.  In the longer run, we might want to deprecate
 the somewhat unintuitive "emptying means deletion" behaviour.


* jc/merge-bases (2014-10-30) 2 commits
  (merged to 'next' on 2014-11-06 at 491e576)
 + get_merge_bases(): always clean-up object flags
 + bisect: clean flags after checking merge bases

 Will cook in 'next' throughout the remainder of the cycle.


* jc/strbuf-add-lines-avoid-sp-ht-sequence (2014-10-27) 1 commit
  (merged to 'next' on 2014-10-29 at 9167582)
 + strbuf_add_commented_lines(): avoid SP-HT sequence in commented lines

 The commented output used to blindly add a SP before the payload
 line, resulting in "# \t<indented text>\n" when the payload began
 with a HT.  Instead, produce "#\t<indented text>\n".

 Will cook in 'next' throughout the remainder of the cycle.


* nd/untracked-cache (2014-10-27) 19 commits
 - t7063: tests for untracked cache
 - update-index: test the system before enabling untracked cache
 - update-index: manually enable or disable untracked cache
 - status: enable untracked cache
 - untracked cache: mark index dirty if untracked cache is updated
 - untracked cache: print stats with $GIT_TRACE_UNTRACKED_STATS
 - untracked cache: avoid racy timestamps
 - read-cache.c: split racy stat test to a separate function
 - untracked cache: invalidate at index addition or removal
 - untracked cache: load from UNTR index extension
 - untracked cache: save to an index extension
 - untracked cache: don't open non-existent .gitignore
 - untracked cache: mark what dirs should be recursed/saved
 - untracked cache: record/validate dir mtime and reuse cached output
 - untracked cache: make a wrapper around {open,read,close}dir()
 - untracked cache: invalidate dirs recursively if .gitignore changes
 - untracked cache: initial untracked cache validation
 - untracked cache: record .gitignore information and dir hierarchy
 - dir.c: optionally compute sha-1 of a .gitignore file


* zk/grep-color-words (2014-10-27) 2 commits
  (merged to 'next' on 2014-10-28 at 4d0457c)
 + Revert "grep: fix match highlighting for combined patterns with context lines"
  (merged to 'next' on 2014-10-24 at 2d2f8f8)
 + grep: fix match highlighting for combined patterns with context lines

 rs/grep-color-words topic solves it in a different way.

 Will discard.


* jc/conflict-hint (2014-10-28) 4 commits
  (merged to 'next' on 2014-10-29 at 693250f)
 + merge & sequencer: turn "Conflicts:" hint into a comment
 + builtin/commit.c: extract ignore_non_trailer() helper function
 + merge & sequencer: unify codepaths that write "Conflicts:" hint
 + builtin/merge.c: drop a parameter that is never used
 (this branch is used by cc/interpret-trailers-more.)

 Unlike all the other hints given in the commit log editor, the list
 of conflicted paths were appended at the end without commented out.

 Will cook in 'next' throughout the remainder of the cycle.


* jc/diff-b-m (2014-10-23) 1 commit
  (merged to 'next' on 2014-10-28 at 4daedb1)
 + diff -B -M: fix output for "copy and then rewrite" case

 Fix long-standing bug in "diff -B -M" output.

 Will cook in 'next' throughout the remainder of the cycle.


* jc/checkout-local-track-report (2014-10-14) 1 commit
  (merged to 'next' on 2014-10-21 at f636a00)
 + checkout: report upstream correctly even with loosely defined branch.*.merge

 The report from "git checkout" on a branch that builds on another
 local branch by setting its branch.*.merge to branch name (not a
 full refname) incorrectly said that the upstream is gone.

 Will cook in 'next' throughout the remainder of the cycle.


* jc/clone-borrow (2014-10-15) 1 commit
  (merged to 'next' on 2014-10-21 at b76ea34)
 + clone: --dissociate option to mark that reference is only temporary

 Allow "git clone --reference" to be used more safely.

 Will cook in 'next' throughout the remainder of the cycle.

--------------------------------------------------
[Discarded]

* jt/timer-settime (2014-08-29) 6 commits
 . use timer_settime() for new platforms
 . autoconf: check for timer_settime()
 . autoconf: check for struct itimerspec
 . autoconf: check for struct sigevent
 . autoconf: check for struct timespec
 . autoconf: check for timer_t

 Was wanting for a reroll.


* rs/ref-transaction-reflog (2014-11-03) 15 commits
 . refs.c: allow deleting refs with a broken sha1
 . refs.c: remove lock_any_ref_for_update
 . refs.c: make unlock_ref/close_ref/commit_ref static
 . refs.c: rename log_ref_setup to create_reflog
 . reflog.c: use a reflog transaction when writing during expire
 . refs.c: allow multiple reflog updates during a single transaction
 . refs.c: only write reflog update if msg is non-NULL
 . refs.c: add a flag to allow reflog updates to truncate the log
 . refs.c: add a transaction function to append a reflog entry
 . copy.c: make copy_fd preserve meaningful errno
 . refs.c: add a function to append a reflog entry to a fd
 . refs.c: add a new update_type field to ref_update
 . refs.c: rename the transaction functions
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c make ref_transaction_create a wrapper to ref_transaction_update
 (this branch is used by rs/ref-transaction-rename and rs/ref-transaction-send-pack.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-rename (2014-11-07) 16 commits
 . refs.c: add an err argument to pack_refs
 . refs.c: make lock_packed_refs take an err argument
 . refs.c: make add_packed_ref return an error instead of calling die
 . refs.c: replace the onerr argument in update_ref with a strbuf err
 . refs.c: make the *_packed_refs functions static
 . refs.c: make repack_without_refs static
 . remote.c: use a transaction for deleting refs
 . refs.c: write updates to packed refs when a transaction has more than one ref
 . refs.c: move reflog updates into its own function
 . refs.c: rollback the lockfile before we die() in repack_without_refs
 . refs.c: update rename_ref to use a transaction
 . refs.c: add transaction support for renaming a reflog
 . refs.c: use a stringlist for repack_without_refs
 . refs.c: use packed refs when deleting refs during a transaction
 . refs.c: return error instead of dying when locking fails during transaction
 . refs.c: allow passing raw git_committer_info as email to _update_reflog
 (this branch is used by rs/ref-transaction-send-pack; uses rs/ref-transaction-reflog.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-send-pack (2014-11-07) 7 commits
 . refs.c: add an err argument to create_symref
 . refs.c: add an err argument to create_reflog
 . t5543-atomic-push.sh: add basic tests for atomic pushes
 . push.c: add an --atomic-push argument
 . receive-pack.c: use a single transaction when atomic-push is negotiated
 . send-pack.c: add an --atomic-push command line argument
 . receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses rs/ref-transaction-reflog and rs/ref-transaction-rename.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* sb/simplify-repack-without-refs (2014-11-20) 1 commit
 . refs.c: use a string_list for repack_without_refs

^ permalink raw reply	[relevance 3%]

* What's cooking in git.git (Dec 2014, #01; Wed, 3)
@ 2014-12-03 21:07  3% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-12-03 21:07 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

People, coming up with new topics is fine, but please pay attention
to what is going around the area you are touching. Does your topic
applied to either 'master' or 'maint' merge cleanly to 'next' and
'pu'?  If not, please coordinate with whoever is working in the same
area.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[New Topics]

* jc/exec-cmd-system-path-leak-fix (2014-11-30) 1 commit
 - system_path(): always return free'able memory to the caller

 The function sometimes returned a non-freeable memory and some
 other times returned a piece of memory that must be freed.

 Will merge to 'next'.


* jc/hook-cleanup (2014-12-01) 1 commit
 - run-command.c: retire unused run_hook_with_custom_index()

 Will merge to 'next'.


* jk/push-simple (2014-11-30) 1 commit
 - push: truly use "simple" as default, not "upstream"

 Will merge to 'next'.


* jn/rerere-fail-on-auto-update-failure (2014-12-03) 2 commits
 - SQUASH???
 - rerere: error out on autoupdate failure


* js/push-to-deploy (2014-11-30) 2 commits
 - t5516: more tests for receive.denyCurrentBranch=updateInstead
 - receive-pack: add another option for receive.denyCurrentBranch
 (this branch is used by jc/push-to-checkout.)

 "git push" into a repository with a working tree normally refuses
 to modify the branch that is checked out.  The command learned to
 optionally do an equivalent of "git reset --hard" only when there
 is no change to the working tree and the index instead, which would
 be useful to "deploy" by pushing into a repository.

 Will merge to 'next'.


* jc/push-to-checkout (2014-12-01) 2 commits
 - receive-pack: support push-to-checkout hook
 - receive-pack: refactor updateInstead codepath
 (this branch uses js/push-to-deploy.)

 Extending the js/push-to-deploy topic, the behaviour of "git push"
 when updating the working tree and the index with an update to the
 branch that is checked out can be tweaked by push-to-checkout hook.

 Needs docs.


* lh/send-email-hide-x-mailer (2014-12-03) 2 commits
 - SQUASH???
 - send-email: add --[no-]xmailer option

 "git send-email" normally identifies itself via X-Mailer: header
 in the message it sends out.  A new command line flag allows the
 header to be squelched.


* nd/list-files (2014-12-01) 19 commits
 - list-files: -M aka diff-cached
 - list-files -F: show submodules with the new indicator '&'
 - list-files: add -F/--classify
 - list-files: show directories as well as files
 - list-files: do not show duplicate cached entries
 - list-files: sort output and remove duplicates
 - list-files: add -t back
 - list-files: add -1 short for --no-column
 - list-files: add -R/--recursive short for --max-depth=-1
 - list-files: -u does not imply showing stages
 - list-files: a user friendly version of ls-files and more
 - ls-files: support --max-depth
 - ls-files: add --column
 - ls-files: add --color to highlight file names
 - ls-files: buffer full item in strbuf before printing
 - ls_colors.c: highlight submodules like directories
 - ls_colors.c: add a function to color a file name
 - ls_colors.c: parse color.ls.* from config file
 - ls_colors.c: add $LS_COLORS parsing code

 A new "git list-files" Porcelain command, "ls-files" with bells and
 whistles.


* nd/ls-tree-pathspec (2014-12-01) 5 commits
 - t3102: style modernization
 - t3102: document that ls-tree does not yet support negated pathspec
 - ls-tree: disable negative pathspec because it's not supported
 - ls-tree: remove path filtering logic in show_tree
 - tree.c: update read_tree_recursive callback to pass strbuf as base

 "git ls-tree" does not support path selection based on negative
 pathspecs, but did not error out when negative pathspecs are given.

 Will merge to 'next'.


* rj/t0050-passes (2014-11-30) 1 commit
 - t0050-*.sh: mark the rename (case change) test as passing

 Will merge to 'next'.


* rt/for-each-ref-spell-tcl-as-Tcl (2014-11-30) 1 commit
 - for-each-ref: correct spelling of Tcl in option description

 Will merge to 'next'.


* sb/ref-transaction-reflog (2014-12-03) 2 commits
 - refs.c: rename transaction.updates to transaction.ref_updates
 - refs.c: rename the transaction functions
 (this branch uses sb/ref-transaction-unify-to-update.)

 Still under review discussion.


* ye/http-accept-language (2014-12-03) 2 commits
 - SQUASH???
 - http: send Accept-Language header if possible

 Still under review discussion.

--------------------------------------------------
[Stalled]

* ms/submodule-update-config-doc (2014-11-03) 1 commit
 - submodule: clarify documentation for update subcommand

 Needs a reroll ($gmane/259037).


* je/quiltimport-no-fuzz (2014-10-21) 2 commits
 - git-quiltimport: flip the default not to allow fuzz
 - git-quiltimport.sh: allow declining fuzz with --exact option

 "quiltimport" drove "git apply" always with -C1 option to reduce
 context of the patch in order to give more chance to somewhat stale
 patches to apply.  Add an "--exact" option to disable, and also
 "-C$n" option to customize this behaviour.  The top patch
 optionally flips the default to "--exact".

 Tired of waiting for an Ack; will discard.


* jc/push-cert-hmac-optim (2014-09-25) 2 commits
 - receive-pack: truncate hmac early and convert only necessary bytes
 - sha1_to_hex: split out "hex-format n bytes" helper and use it

 This is "we could do this if we wanted to", not "we measured and it
 improves performance critical codepath".

 Will perhaps drop.


* mt/patch-id-stable (2014-06-10) 1 commit
 - patch-id: change default to stable

 Teaches "git patch-id" to compute the patch ID that does not change
 when the files in a single patch is reordered. As this new algorithm
 is backward incompatible, the last bit to flip it to be the default
 is left out of 'master' for now.

 Nobody seems to be jumping up & down requesting this last step,
 which makes the result somewhat backward incompatible.
 Will perhaps drop.


* tr/remerge-diff (2014-11-10) 9 commits
 - t4213: avoid "|" in sed regexp
 - log --remerge-diff: show what the conflict resolution changed
 - name-hash: allow dir hashing even when !ignore_case
 - merge-recursive: allow storing conflict hunks in index
 - merge_diff_mode: fold all merge diff variants into an enum
 - combine-diff: do not pass revs->dense_combined_merges redundantly
 - merge-recursive: -Xindex-only to leave worktree unchanged
 - merge-recursive: internal flag to avoid touching the worktree
 - merge-recursive: remove dead conditional in update_stages()

 "log -p" output learns a new way to let users inspect a merge
 commit by showing the differences between the automerged result
 with conflicts the person who recorded the merge would have seen
 and the final conflict resolution that was recorded in the merge.

 Waiting for a reroll ($gmane/256591).


* hv/submodule-config (2014-11-11) 4 commits
 - do not die on error of parsing fetchrecursesubmodules option
 - use new config API for worktree configurations of submodules
 - extract functions for submodule config set and lookup
 - implement submodule config cache for lookup of submodule names

 Kicked back to 'pu' per request ($gmane/255610).


* ab/add-interactive-show-diff-func-name (2014-05-12) 2 commits
 - SQUASH??? git-add--interactive: Preserve diff heading when splitting hunks
 - git-add--interactive: Preserve diff heading when splitting hunks

 Waiting for a reroll.


* jn/gitweb-utf8-in-links (2014-05-27) 1 commit
 - gitweb: Harden UTF-8 handling in generated links

 $gmane/250758?


* ss/userdiff-update-csharp-java (2014-06-02) 2 commits
 - userdiff: support Java try keyword
 - userdiff: support C# async methods and correct C# keywords

 Reviews sent; waiting for a response.


* bg/rebase-off-of-previous-branch (2014-04-16) 1 commit
 - git-rebase: print name of rev when using shorthand

 Teach "git rebase -" to report the concrete name of the branch
 (i.e. the previous one).

 But it stops short and does not do the same for "git rebase @{-1}".
 Expecting a reroll.


* rb/merge-prepare-commit-msg-hook (2014-01-10) 4 commits
 - merge: drop unused arg from abort_commit method signature
 - merge: make prepare_to_commit responsible for write_merge_state
 - t7505: ensure cleanup after hook blocks merge
 - t7505: add missing &&

 Expose more merge states (e.g. $GIT_DIR/MERGE_MODE) to hooks that
 run during "git merge".  The log message stresses too much on one
 hook, prepare-commit-msg, but it would equally apply to other hooks
 like post-merge, I think.

 Waiting for a reroll.


* jc/graph-post-root-gap (2013-12-30) 3 commits
 - WIP: document what we want at the end
 - graph: remove unused code a bit
 - graph: stuff the current commit into graph->columns[]

 This was primarily a RFH ($gmane/239580).


* tg/perf-lib-test-perf-cleanup (2013-09-19) 2 commits
 - perf-lib: add test_perf_cleanup target
 - perf-lib: split starting the test from the execution

 Add test_perf_cleanup shell function to the perf suite, that allows
 the script writers to define a test with a clean-up action.

 Will hold.


* jc/show-branch (2014-03-24) 5 commits
 - show-branch: use commit slab to represent bitflags of arbitrary width
 - show-branch.c: remove "all_mask"
 - show-branch.c: abstract out "flags" operation
 - show-branch.c: lift all_mask/all_revs to a global static
 - show-branch.c: update comment style

 Waiting for the final step to lift the hard-limit before sending it out.

--------------------------------------------------
[Cooking]

* jk/pack-bitmap (2014-11-30) 1 commit
 - pack-bitmap: do not use gcc packed attribute

 Will merge to 'next'.


* nd/multiple-work-trees (2014-12-01) 34 commits
 - git-common-dir: make "modules/" per-working-directory directory
 - checkout: do not fail if target is an empty directory
 - t2025: add a test to make sure grafts is working from a linked checkout
 - checkout: don't require a work tree when checking out into a new one
 - git_path(): keep "info/sparse-checkout" per work-tree
 - count-objects: report unused files in $GIT_DIR/worktrees/...
 - gc: support prune --worktrees
 - gc: factor out gc.pruneexpire parsing code
 - gc: style change -- no SP before closing parenthesis
 - checkout: clean up half-prepared directories in --to mode
 - checkout: reject if the branch is already checked out elsewhere
 - prune: strategies for linked checkouts
 - checkout: support checking out into a new working directory
 - use new wrapper write_file() for simple file writing
 - wrapper.c: wrapper to open a file, fprintf then close
 - setup.c: support multi-checkout repo setup
 - setup.c: detect $GIT_COMMON_DIR check_repository_format_gently()
 - setup.c: convert check_repository_format_gently to use strbuf
 - setup.c: detect $GIT_COMMON_DIR in is_git_directory()
 - setup.c: convert is_git_directory() to use strbuf
 - git-stash: avoid hardcoding $GIT_DIR/logs/....
 - *.sh: avoid hardcoding $GIT_DIR/hooks/...
 - git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects
 - $GIT_COMMON_DIR: a new environment variable
 - commit: use SEQ_DIR instead of hardcoding "sequencer"
 - fast-import: use git_path() for accessing .git dir instead of get_git_dir()
 - reflog: avoid constructing .lock path with git_path
 - *.sh: respect $GIT_INDEX_FILE
 - git_path(): be aware of file relocation in $GIT_DIR
 - path.c: group git_path(), git_pathdup() and strbuf_git_path() together
 - path.c: rename vsnpath() to do_git_path()
 - git_snpath(): retire and replace with strbuf_git_path()
 - path.c: make get_pathname() call sites return const char *
 - path.c: make get_pathname() return strbuf instead of static buffer

 A replacement for contrib/workdir/git-new-workdir that does not
 rely on symbolic links and make sharing of objects and refs safer
 by making the borrowee and borrowers aware of each other.

 A few tests need some tweaks for MinGW ($gmane/{257756,257757}).
 Conflicts with rs/ref-transaction so ejected for now, waiting for a
 reroll.


* jc/unpack-trees-plug-leak (2014-11-17) 1 commit
 - unpack_trees: plug leakage of o->result

 Will merge to 'next'.


* js/windows-open-eisdir-error (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at 57b0d49)
 + Windows: correct detection of EISDIR in mingw_open()

 Will merge to 'master'.


* rs/maint-config-use-labs (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at 53c2404)
 + use labs() for variables of type long instead of abs()

 Will merge to 'master'.


* rs/receive-pack-use-labs (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at c6d2d94)
 + use labs() for variables of type long instead of abs()

 Will merge to 'master'.


* jk/colors (2014-11-20) 5 commits
 - diff-highlight: allow configurable colors
 - parse_color: recognize "no$foo" to clear the $foo attribute
 - parse_color: support 24-bit RGB values
 - parse_color: refactor color storage
 - Merge branch 'jn/parse-config-slot' into jk/colors
 (this branch uses jk/colors-fix.)

 Will merge to 'next'.


* jk/colors-fix (2014-11-20) 3 commits
 - t4026: test "normal" color
 - config: fix parsing of "git config --get-color some.key -1"
 - docs: describe ANSI 256-color mode
 (this branch is used by jk/colors.)

 Will merge to 'next'.


* jk/gitweb-with-newer-cgi-multi-param (2014-11-18) 1 commit
  (merged to 'next' on 2014-11-18 at 6ac61fe)
 + gitweb: hack around CGI's list-context param() handling

 Will merge to 'master'.


* jk/lock-ref-sha1-basic-return-errors (2014-11-20) 1 commit
 - lock_ref_sha1_basic: do not die on locking errors

 Will merge to 'next'.


* jk/no-perl-tests (2014-11-18) 2 commits
 - t960[34]: mark cvsimport tests as requiring perl
 - t0090: mark add-interactive test with PERL prerequisite

 Will merge to 'next'.


* jk/rebuild-perl-scripts-with-no-perl-seting-change (2014-11-18) 3 commits
 - Makefile: have python scripts depend on NO_PYTHON setting
 - Makefile: simplify by using SCRIPT_{PERL,SH}_GEN macros
 - Makefile: have perl scripts depend on NO_PERL setting

 Will merge to 'next'.


* mh/config-copy-string-from-git-path (2014-11-17) 1 commit
 - cmd_config(): make a copy of path obtained from git_path()

 Will merge to 'next'.


* mh/config-flip-xbit-back-after-checking (2014-11-18) 1 commit
  (merged to 'next' on 2014-11-18 at 45f7d71)
 + create_default_files(): don't set u+x bit on $GIT_DIR/config
 (this branch is used by tb/config-core-filemode-check-on-broken-fs.)

 Will merge to 'master'.


* po/everyday-doc (2014-11-17) 1 commit
 - Documentation: change "gitlink" typo in git-push

 Will merge to 'next'.


* ps/new-workdir-into-empty-directory (2014-12-03) 1 commit
 - git-new-workdir: don't fail if the target directory is empty

 Will merge to 'next'.


* rt/push-recurse-submodule-usage-string (2014-11-18) 1 commit
 - builtin/push.c: fix description of --recurse-submodules option

 Will merge to 'next'.


* sb/copy-fd-errno (2014-11-17) 1 commit
 - copy.c: make copy_fd preserve meaningful errno

 Jonathan seems to be working in the same area, having a moral
 equivalent.  Have to drop either this or the other one.


* sb/log-ref-write-fd (2014-11-20) 1 commit
 - refs.c: add a function to append a reflog entry to a fd

 Moves a part of function around to add a helper that still only has
 one caller.  Need to see how this helps in a bigger picture;
 conflicts with nd/multiple-work-trees.


* sb/ref-transaction-unify-to-update (2014-11-20) 2 commits
 - refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 - refs.c: make ref_transaction_create a wrapper for ref_transaction_update
 (this branch is used by sb/ref-transaction-reflog.)

 Code simplification.

 Will merge to 'next'.


* sv/doc-stripspace (2014-11-19) 1 commit
 - Documentation/git-stripspace: Update synopsis

 Will merge to 'next'.


* sv/typofix-apply-error-message (2014-11-17) 1 commit
 - apply: fix typo in an error message

 Will merge to 'next'.


* da/difftool-mergetool-simplify-reporting-status (2014-11-21) 5 commits
 - mergetools: stop setting $status in merge_cmd()
 - mergetool: simplify conditionals
 - difftool--helper: add explicit exit statement
 - mergetool--lib: remove use of $status global
 - mergetool--lib: remove no-op assignment to $status from setup_user_tool

 Will merge to 'next'.


* dw/shell-basename-dashdash-before-stripping-leading-dash-from-login (2014-11-25) 1 commit
 - git-sh-setup.sh: use dashdash with basename call

 Will merge to 'next'.


* jc/refer-to-t-readme-from-submitting-patches (2014-11-24) 2 commits
 - t/README: justify why "! grep foo" is sufficient
 - SubmittingPatches: refer to t/README for tests

 Will merge to 'next'.


* jc/t9001-modernise (2014-11-25) 5 commits
 - t9001: style modernisation phase #5
 - t9001: style modernisation phase #4
 - t9001: style modernisation phase #3
 - t9001: style modernisation phase #2
 - t9001: style modernisation phase #1
 (this branch uses pb/send-email-te.)


* js/t5000-dont-copy-bin-sh (2014-11-24) 1 commit
 - t5000 on Windows: do not mistake "sh.exe" as "sh"

 Will merge to 'next'.


* mg/add-ignore-errors (2014-11-21) 1 commit
 - add: ignore only ignored files

 Will merge to 'next'.


* mh/find-uniq-abbrev (2014-11-26) 1 commit
 - sha1_name: avoid unnecessary sha1 lookup in find_unique_abbrev

 Will merge to 'next'.


* mh/simplify-repack-without-refs (2014-11-25) 7 commits
 - sort_string_list(): rename to string_list_sort()
 - prune_remote(): iterate using for_each_string_list_item()
 - prune_remote(): rename local variable
 - repack_without_refs(): make the refnames argument a string_list
 - prune_remote(): sort delete_refs_list references en masse
 - prune_remote(): initialize both delete_refs lists in a single loop
 - prune_remote(): exit early if there are no stale references

 Will merge to 'next'.


* pb/am-message-id-footer (2014-11-25) 2 commits
 - git-am: add --message-id/--no-message-id
 - git-mailinfo: add --message-id

 Will merge to 'next'.


* pb/send-email-te (2014-11-25) 2 commits
 - git-send-email: add --transfer-encoding option
 - git-send-email: delay creation of MIME headers
 (this branch is used by jc/t9001-modernise.)

 Will merge to 'next'.


* pw/remote-set-url-fetch (2014-11-26) 1 commit
 - remote: add --fetch and --both options to set-url

 Still under discussion.


* rj/no-xopen-source-for-cygwin (2014-11-24) 1 commit
 - git-compat-util.h: don't define _XOPEN_SOURCE on cygwin

 Will merge to 'next'.


* sb/string-list (2014-11-30) 4 commits
 - string_list: remove string_list_insert_at_index() from its API
 - SQUASH???
 - mailmap: use higher level string list functions
 - string_list: document string_list_(insert,lookup)

 Will merge to 'next' after squashing the fixup.


* sb/write-sha1-update-reflog (2014-11-24) 1 commit
 - refs.c: move reflog updates into its own function

 Moves a part of function around to add a helper that still only has
 one caller.  Need to see how this helps in a bigger picture.


* tb/config-core-filemode-check-on-broken-fs (2014-11-21) 1 commit
 - init-db: improve the filemode trustability check
 (this branch uses mh/config-flip-xbit-back-after-checking.)

 Will merge to 'next'.


* jk/approxidate-avoid-y-d-m-over-future-dates (2014-11-13) 2 commits
  (merged to 'next' on 2014-11-14 at 3c11a1b)
 + approxidate: allow ISO-like dates far in the future
 + pass TIME_DATE_NOW to approxidate future-check

 Traditionally we tried to avoid interpreting date strings given by
 the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
 used early November 2014 was taken as "October 12, 2014" because it
 is likely that a date in the future, December 10, is a mistake.

 Loosen this and do not tiebreak by future-ness of the date when

 (1) ISO-like format is used, and
 (2) the string can make sense interpreted as both y-m-d and y-d-m.

 Will cook in 'next'.


* jk/checkout-from-tree (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at ddbffb0)
 + checkout $tree: do not throw away unchanged index entries

 Will merge to 'master'.


* mb/enable-lib-terminal-test-on-newer-darwin (2014-11-14) 1 commit
  (merged to 'next' on 2014-11-14 at b2aae27)
 + t/lib-terminal: allow TTY tests to run under recent Mac OS

 We probably should drop this ($gmane/259609).


* sv/get-builtin (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at 9497e17)
 + builtin: move builtin retrieval to get_builtin()

 Will merge to 'master'.


* br/imap-send-verbosity (2014-11-05) 1 commit
  (merged to 'next' on 2014-11-12 at d9e58ec)
 + imap-send: use parse options API to determine verbosity
 (this branch is used by br/imap-send-via-libcurl.)

 Will cook in 'next'.


* br/imap-send-via-libcurl (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-12 at 5327ab4)
 + git-imap-send: use libcurl for implementation
 (this branch uses br/imap-send-verbosity.)

 Will cook in 'next'.


* cc/interpret-trailers-more (2014-11-10) 4 commits
 - trailer: add test with an old style conflict block
 - trailer: reuse ignore_non_trailer() to ignore conflict lines
 - commit: make ignore_non_trailer() non static
 - Merge branch 'jc/conflict-hint' into cc/interpret-trailers-more
 (this branch uses jc/conflict-hint.)

 Will merge to 'next'.


* rs/env-array-in-child-process (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-14 at 3f6ba07)
 + use args member of struct child_process

 Will merge to 'master'.


* tq/git-ssh-command (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-14 at 83f5dae)
 + git_connect: set ssh shell command in GIT_SSH_COMMAND

 Allow passing extra set of arguments when ssh is invoked to create
 an encrypted & authenticated connection, which is not possible with
 existing GIT_SSH mechanism, which was designed more to match what
 other programs with similar variables did, not necessarily to be
 more useful.

 Will merge to 'master'.


* nd/lockfile-absolute (2014-11-03) 1 commit
  (merged to 'next' on 2014-11-06 at 68722a9)
 + lockfile.c: store absolute path

 The lockfile API can get confused which file to clean up when the
 process moved the $cwd after creating a lockfile.

 Will cook in 'next'.


* jh/empty-notes (2014-11-14) 9 commits
  (merged to 'next' on 2014-11-18 at 9eeb338)
 + t3301: modernize style
 + notes: empty notes should be shown by 'git log'
 + builtin/notes: add --allow-empty, to allow storing empty notes
 + builtin/notes: split create_note() to clarify add vs. remove logic
 + builtin/notes: simplify early exit code in add()
 + builtin/notes: refactor note file path into struct note_data
 + builtin/notes: improve naming
 + t3301: verify that 'git notes' removes empty notes by default
 + builtin/notes: fix premature failure when trying to add the empty blob

 A request to store an empty note via "git notes" meant to remove
 note from the object but with --allow-empty we will store a (surprise!)
 note that is empty.  In the longer run, we might want to deprecate
 the somewhat unintuitive "emptying means deletion" behaviour.

 Will merge to 'master'.


* jc/merge-bases (2014-10-30) 2 commits
  (merged to 'next' on 2014-11-06 at 491e576)
 + get_merge_bases(): always clean-up object flags
 + bisect: clean flags after checking merge bases

 Will cook in 'next'.


* jc/strbuf-add-lines-avoid-sp-ht-sequence (2014-10-27) 1 commit
  (merged to 'next' on 2014-10-29 at 9167582)
 + strbuf_add_commented_lines(): avoid SP-HT sequence in commented lines

 The commented output used to blindly add a SP before the payload
 line, resulting in "# \t<indented text>\n" when the payload began
 with a HT.  Instead, produce "#\t<indented text>\n".

 Will cook in 'next'.


* nd/untracked-cache (2014-10-27) 19 commits
 - t7063: tests for untracked cache
 - update-index: test the system before enabling untracked cache
 - update-index: manually enable or disable untracked cache
 - status: enable untracked cache
 - untracked cache: mark index dirty if untracked cache is updated
 - untracked cache: print stats with $GIT_TRACE_UNTRACKED_STATS
 - untracked cache: avoid racy timestamps
 - read-cache.c: split racy stat test to a separate function
 - untracked cache: invalidate at index addition or removal
 - untracked cache: load from UNTR index extension
 - untracked cache: save to an index extension
 - untracked cache: don't open non-existent .gitignore
 - untracked cache: mark what dirs should be recursed/saved
 - untracked cache: record/validate dir mtime and reuse cached output
 - untracked cache: make a wrapper around {open,read,close}dir()
 - untracked cache: invalidate dirs recursively if .gitignore changes
 - untracked cache: initial untracked cache validation
 - untracked cache: record .gitignore information and dir hierarchy
 - dir.c: optionally compute sha-1 of a .gitignore file

 Comments?


* zk/grep-color-words (2014-10-27) 2 commits
  (merged to 'next' on 2014-10-28 at 4d0457c)
 + Revert "grep: fix match highlighting for combined patterns with context lines"
  (merged to 'next' on 2014-10-24 at 2d2f8f8)
 + grep: fix match highlighting for combined patterns with context lines

 rs/grep-color-words topic solves it in a different way.

 Will discard.


* jc/conflict-hint (2014-10-28) 4 commits
  (merged to 'next' on 2014-10-29 at 693250f)
 + merge & sequencer: turn "Conflicts:" hint into a comment
 + builtin/commit.c: extract ignore_non_trailer() helper function
 + merge & sequencer: unify codepaths that write "Conflicts:" hint
 + builtin/merge.c: drop a parameter that is never used
 (this branch is used by cc/interpret-trailers-more.)

 Unlike all the other hints given in the commit log editor, the list
 of conflicted paths were appended at the end without commented out.

 Will cook in 'next'.


* jc/diff-b-m (2014-10-23) 1 commit
  (merged to 'next' on 2014-10-28 at 4daedb1)
 + diff -B -M: fix output for "copy and then rewrite" case

 Fix long-standing bug in "diff -B -M" output.

 Will cook in 'next'.


* jc/checkout-local-track-report (2014-10-14) 1 commit
  (merged to 'next' on 2014-10-21 at f636a00)
 + checkout: report upstream correctly even with loosely defined branch.*.merge

 The report from "git checkout" on a branch that builds on another
 local branch by setting its branch.*.merge to branch name (not a
 full refname) incorrectly said that the upstream is gone.

 Will cook in 'next'.


* jc/clone-borrow (2014-10-15) 1 commit
  (merged to 'next' on 2014-10-21 at b76ea34)
 + clone: --dissociate option to mark that reference is only temporary

 Allow "git clone --reference" to be used more safely.

 Will cook in 'next'.

--------------------------------------------------
[Discarded]

* jt/timer-settime (2014-08-29) 6 commits
 . use timer_settime() for new platforms
 . autoconf: check for timer_settime()
 . autoconf: check for struct itimerspec
 . autoconf: check for struct sigevent
 . autoconf: check for struct timespec
 . autoconf: check for timer_t

 Was wanting for a reroll.


* rs/ref-transaction-reflog (2014-11-03) 15 commits
 . refs.c: allow deleting refs with a broken sha1
 . refs.c: remove lock_any_ref_for_update
 . refs.c: make unlock_ref/close_ref/commit_ref static
 . refs.c: rename log_ref_setup to create_reflog
 . reflog.c: use a reflog transaction when writing during expire
 . refs.c: allow multiple reflog updates during a single transaction
 . refs.c: only write reflog update if msg is non-NULL
 . refs.c: add a flag to allow reflog updates to truncate the log
 . refs.c: add a transaction function to append a reflog entry
 . copy.c: make copy_fd preserve meaningful errno
 . refs.c: add a function to append a reflog entry to a fd
 . refs.c: add a new update_type field to ref_update
 . refs.c: rename the transaction functions
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c make ref_transaction_create a wrapper to ref_transaction_update
 (this branch is used by rs/ref-transaction-rename and rs/ref-transaction-send-pack.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-rename (2014-11-07) 16 commits
 . refs.c: add an err argument to pack_refs
 . refs.c: make lock_packed_refs take an err argument
 . refs.c: make add_packed_ref return an error instead of calling die
 . refs.c: replace the onerr argument in update_ref with a strbuf err
 . refs.c: make the *_packed_refs functions static
 . refs.c: make repack_without_refs static
 . remote.c: use a transaction for deleting refs
 . refs.c: write updates to packed refs when a transaction has more than one ref
 . refs.c: move reflog updates into its own function
 . refs.c: rollback the lockfile before we die() in repack_without_refs
 . refs.c: update rename_ref to use a transaction
 . refs.c: add transaction support for renaming a reflog
 . refs.c: use a stringlist for repack_without_refs
 . refs.c: use packed refs when deleting refs during a transaction
 . refs.c: return error instead of dying when locking fails during transaction
 . refs.c: allow passing raw git_committer_info as email to _update_reflog
 (this branch is used by rs/ref-transaction-send-pack; uses rs/ref-transaction-reflog.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-send-pack (2014-11-07) 7 commits
 . refs.c: add an err argument to create_symref
 . refs.c: add an err argument to create_reflog
 . t5543-atomic-push.sh: add basic tests for atomic pushes
 . push.c: add an --atomic-push argument
 . receive-pack.c: use a single transaction when atomic-push is negotiated
 . send-pack.c: add an --atomic-push command line argument
 . receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses rs/ref-transaction-reflog and rs/ref-transaction-rename.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* sb/simplify-repack-without-refs (2014-11-20) 1 commit
 . refs.c: use a string_list for repack_without_refs

^ permalink raw reply	[relevance 3%]

* What's cooking in git.git (Dec 2014, #02; Wed, 10)
@ 2014-12-10 22:38  3% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-12-10 22:38 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[Graduated to "master"]

* jh/empty-notes (2014-11-14) 9 commits
  (merged to 'next' on 2014-11-18 at 9eeb338)
 + t3301: modernize style
 + notes: empty notes should be shown by 'git log'
 + builtin/notes: add --allow-empty, to allow storing empty notes
 + builtin/notes: split create_note() to clarify add vs. remove logic
 + builtin/notes: simplify early exit code in add()
 + builtin/notes: refactor note file path into struct note_data
 + builtin/notes: improve naming
 + t3301: verify that 'git notes' removes empty notes by default
 + builtin/notes: fix premature failure when trying to add the empty blob

 A request to store an empty note via "git notes" meant to remove
 note from the object but with --allow-empty we will store a (surprise!)
 note that is empty.  In the longer run, we might want to deprecate
 the somewhat unintuitive "emptying means deletion" behaviour.


* jk/checkout-from-tree (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at ddbffb0)
 + checkout $tree: do not throw away unchanged index entries

 "git checkout $treeish $path", when $path in the index and the
 working tree already matched what is in $treeish at the $path,
 still overwrote the $path unnecessarily.


* jk/gitweb-with-newer-cgi-multi-param (2014-11-18) 1 commit
  (merged to 'next' on 2014-11-18 at 6ac61fe)
 + gitweb: hack around CGI's list-context param() handling

 "gitweb" used to depend on a behaviour recent CGI.pm deprecated.


* js/windows-open-eisdir-error (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at 57b0d49)
 + Windows: correct detection of EISDIR in mingw_open()

 open() emulated on Windows platforms did not give EISDIR upon an
 attempt to open a directory for writing.


* mh/config-flip-xbit-back-after-checking (2014-11-18) 1 commit
  (merged to 'next' on 2014-11-18 at 45f7d71)
 + create_default_files(): don't set u+x bit on $GIT_DIR/config
 (this branch is used by tb/config-core-filemode-check-on-broken-fs.)

 "git init" (hence "git clone") initialized the per-repository
 configuration file .git/config with x-bit by mistake.


* rs/env-array-in-child-process (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-14 at 3f6ba07)
 + use args member of struct child_process

 Code cleanup.


* rs/maint-config-use-labs (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at 53c2404)
 + use labs() for variables of type long instead of abs()

 A few code paths used abs() when they should have used labs() on
 long integers.


* rs/receive-pack-use-labs (2014-11-17) 1 commit
  (merged to 'next' on 2014-11-18 at c6d2d94)
 + use labs() for variables of type long instead of abs()

 A few code paths used abs() when they should have used labs() on
 long integers.


* sv/get-builtin (2014-11-13) 1 commit
  (merged to 'next' on 2014-11-14 at 9497e17)
 + builtin: move builtin retrieval to get_builtin()

 Small code consolidation.


* tq/git-ssh-command (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-14 at 83f5dae)
 + git_connect: set ssh shell command in GIT_SSH_COMMAND

 Allow passing extra set of arguments when ssh is invoked to create
 an encrypted & authenticated connection, which is not possible with
 existing GIT_SSH mechanism, which was designed more to match what
 other programs with similar variables did, not necessarily to be
 more useful.

--------------------------------------------------
[New Topics]

* dm/compat-s-ifmt-for-zos (2014-12-04) 1 commit
 - compat: convert modes to use portable file type values

 Long overdue departure from the assumption that S_IFMT is shared by
 everybody made in 2005.


* jk/credential-quit (2014-12-04) 2 commits
 - prompt: respect GIT_TERMINAL_PROMPT to disable terminal prompts
 - credential: let helpers tell us to quit

 Credential helpers are asked in turn until one of them give
 positive response, which is cumbersome to turn off when you need to
 run Git in an automated setting.  The credential helper interface
 learned to allow a helper to say "stop, don't ask other helpers."
 Also GIT_TERMINAL_PROMPT environment can be set to false to disable
 our built-in prompt mechanism for passwords.

 Will merge to 'next'.


* mg/branch-d-m-f (2014-12-09) 2 commits
 - branch: allow -f with -m and -d
 - t3200-branch: test -M

 "git branch -d" (delete) and "git branch -m" (move) learned to
 honor "-f" (force) flag; unlike many other subcommands, the way to
 force these have been with separate "-D/-M" options, which was
 inconsistent.

 Will merge to 'next'.


* mg/doc-check-ignore-tracked-are-not-ignored (2014-12-04) 1 commit
 - check-ignore: clarify treatment of tracked files

 Will merge to 'next'.


* rt/completion-tag (2014-12-04) 1 commit
 - completion: add git-tag options

 Will merge to 'next'.


* jk/for-each-reflog-ent-reverse (2014-12-05) 2 commits
 - for_each_reflog_ent_reverse: turn leftover check into assertion
 - for_each_reflog_ent_reverse: fix newlines on block boundaries

 Will merge to 'next'.


* po/doc-assume-unchanged (2014-12-09) 2 commits
 - gitignore.txt: do not suggest assume-unchanged
 - doc: make clear --assume-unchanged's user contract

 Fixes long-standing misunderstanding of what assume-unchanged is
 about.  Some text near what is removed by the bottom patch may also
 have to be removed.

 Will merge to 'next'.


* tb/t0027-eol-conversion (2014-12-05) 1 commit
 - t0027: check the eol conversion warnings

 Will merge to 'next'.


* jk/always-allow-large-packets (2014-12-10) 1 commit
 - pkt-line: allow writing of LARGE_PACKET_MAX buffers

 Will merge to 'next'.


* jk/commit-date-approxidate (2014-12-10) 2 commits
 - commit: always populate GIT_AUTHOR_* variables
 - commit: loosen ident checks when generating template

 Will merge to 'next'.


* jk/read-packed-refs-without-path-max (2014-12-10) 3 commits
 - read_packed_refs: use skip_prefix instead of static array
 - read_packed_refs: pass strbuf to parse_ref_line
 - read_packed_refs: use a strbuf for reading lines

 Will merge to 'next'.


* jn/dedup-doc-header (2014-12-09) 2 commits
 - put string-list API documentation in one place
 - put strbuf API documentation in one place

 We would want to have an easy way for developers to learn about
 APIs, and also a way to encourage them to keep the API
 documentation up to date when they make changes.  Having header
 comments and API documentation duplicated in two different places
 risked them going out of sync.

 This removes the duplicates by dropping comments from the header;
 it is just for discussion at this moment.


* jn/doc-api-errors (2014-12-04) 1 commit
 - doc: document error handling functions and conventions

 For discussion.


* js/fsck-tag-validation (2014-12-09) 2 commits
 - index-pack: terminate object buffers with NUL
 - fsck: properly bound "invalid tag name" error message

 Follow-up to tag object format validation added in 2.2.

 Will merge to 'next'.


* js/test-hashmap-squelch-gcc (2014-12-09) 1 commit
 - test-hashmap: squelch gcc compiler warning

 Will merge to 'next'.


* ok/rebase-i-count-todo (2014-12-10) 1 commit
 - Show number of TODO items for interactive rebase

 Will merge to 'next'.


* rw/apply-does-not-take-ignore-date (2014-12-09) 1 commit
 - git-am.txt: --ignore-date flag is not passed to git-apply


 Will merge to 'next'.

--------------------------------------------------
[Stalled]

* ms/submodule-update-config-doc (2014-11-03) 1 commit
 - submodule: clarify documentation for update subcommand

 Needs a reroll ($gmane/259037).


* je/quiltimport-no-fuzz (2014-10-21) 2 commits
 - git-quiltimport: flip the default not to allow fuzz
 - git-quiltimport.sh: allow declining fuzz with --exact option

 "quiltimport" drove "git apply" always with -C1 option to reduce
 context of the patch in order to give more chance to somewhat stale
 patches to apply.  Add an "--exact" option to disable, and also
 "-C$n" option to customize this behaviour.  The top patch
 optionally flips the default to "--exact".

 Tired of waiting for an Ack; will discard.


* jc/push-cert-hmac-optim (2014-09-25) 2 commits
 - receive-pack: truncate hmac early and convert only necessary bytes
 - sha1_to_hex: split out "hex-format n bytes" helper and use it

 This is "we could do this if we wanted to", not "we measured and it
 improves performance critical codepath".

 Will perhaps drop.


* mt/patch-id-stable (2014-06-10) 1 commit
 - patch-id: change default to stable

 Teaches "git patch-id" to compute the patch ID that does not change
 when the files in a single patch is reordered. As this new algorithm
 is backward incompatible, the last bit to flip it to be the default
 is left out of 'master' for now.

 Nobody seems to be jumping up & down requesting this last step,
 which makes the result somewhat backward incompatible.
 Will perhaps drop.


* tr/remerge-diff (2014-11-10) 9 commits
 - t4213: avoid "|" in sed regexp
 - log --remerge-diff: show what the conflict resolution changed
 - name-hash: allow dir hashing even when !ignore_case
 - merge-recursive: allow storing conflict hunks in index
 - merge_diff_mode: fold all merge diff variants into an enum
 - combine-diff: do not pass revs->dense_combined_merges redundantly
 - merge-recursive: -Xindex-only to leave worktree unchanged
 - merge-recursive: internal flag to avoid touching the worktree
 - merge-recursive: remove dead conditional in update_stages()

 "log -p" output learns a new way to let users inspect a merge
 commit by showing the differences between the automerged result
 with conflicts the person who recorded the merge would have seen
 and the final conflict resolution that was recorded in the merge.

 Waiting for a reroll ($gmane/256591).


* hv/submodule-config (2014-11-11) 4 commits
 - do not die on error of parsing fetchrecursesubmodules option
 - use new config API for worktree configurations of submodules
 - extract functions for submodule config set and lookup
 - implement submodule config cache for lookup of submodule names

 Kicked back to 'pu' per request ($gmane/255610).


* ab/add-interactive-show-diff-func-name (2014-05-12) 2 commits
 - SQUASH??? git-add--interactive: Preserve diff heading when splitting hunks
 - git-add--interactive: Preserve diff heading when splitting hunks

 Waiting for a reroll.


* jn/gitweb-utf8-in-links (2014-05-27) 1 commit
 - gitweb: Harden UTF-8 handling in generated links

 $gmane/250758?


* ss/userdiff-update-csharp-java (2014-06-02) 2 commits
 - userdiff: support Java try keyword
 - userdiff: support C# async methods and correct C# keywords

 Reviews sent; waiting for a response.


* bg/rebase-off-of-previous-branch (2014-04-16) 1 commit
 - git-rebase: print name of rev when using shorthand

 Teach "git rebase -" to report the concrete name of the branch
 (i.e. the previous one).

 But it stops short and does not do the same for "git rebase @{-1}".
 Expecting a reroll.


* rb/merge-prepare-commit-msg-hook (2014-01-10) 4 commits
 - merge: drop unused arg from abort_commit method signature
 - merge: make prepare_to_commit responsible for write_merge_state
 - t7505: ensure cleanup after hook blocks merge
 - t7505: add missing &&

 Expose more merge states (e.g. $GIT_DIR/MERGE_MODE) to hooks that
 run during "git merge".  The log message stresses too much on one
 hook, prepare-commit-msg, but it would equally apply to other hooks
 like post-merge, I think.

 Waiting for a reroll.


* jc/graph-post-root-gap (2013-12-30) 3 commits
 - WIP: document what we want at the end
 - graph: remove unused code a bit
 - graph: stuff the current commit into graph->columns[]

 This was primarily a RFH ($gmane/239580).


* tg/perf-lib-test-perf-cleanup (2013-09-19) 2 commits
 - perf-lib: add test_perf_cleanup target
 - perf-lib: split starting the test from the execution

 Add test_perf_cleanup shell function to the perf suite, that allows
 the script writers to define a test with a clean-up action.

 Will hold.


* jc/show-branch (2014-03-24) 5 commits
 - show-branch: use commit slab to represent bitflags of arbitrary width
 - show-branch.c: remove "all_mask"
 - show-branch.c: abstract out "flags" operation
 - show-branch.c: lift all_mask/all_revs to a global static
 - show-branch.c: update comment style

 Waiting for the final step to lift the hard-limit before sending it out.

--------------------------------------------------
[Cooking]

* jc/exec-cmd-system-path-leak-fix (2014-11-30) 1 commit
 - system_path(): always return free'able memory to the caller

 The function sometimes returned a non-freeable memory and some
 other times returned a piece of memory that must be freed.

 Will merge to 'next'.


* jc/hook-cleanup (2014-12-01) 1 commit
  (merged to 'next' on 2014-12-04 at 17059f5)
 + run-command.c: retire unused run_hook_with_custom_index()

 Remove unused code.

 Will merge to 'master'.


* jk/push-simple (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-04 at 00785c7)
 + push: truly use "simple" as default, not "upstream"

 Git 2.0 was supposed to make the "simple" mode for the default of
 "git push", but it didn't.

 Will merge to 'master'.


* jn/rerere-fail-on-auto-update-failure (2014-12-03) 2 commits
 - SQUASH???
 - rerere: error out on autoupdate failure

 Will be rerolled as a part of a larger series.


* js/push-to-deploy (2014-11-30) 2 commits
 - t5516: more tests for receive.denyCurrentBranch=updateInstead
 - receive-pack: add another option for receive.denyCurrentBranch
 (this branch is used by jc/push-to-checkout.)

 "git push" into a repository with a working tree normally refuses
 to modify the branch that is checked out.  The command learned to
 optionally do an equivalent of "git reset --hard" only when there
 is no change to the working tree and the index instead, which would
 be useful to "deploy" by pushing into a repository.

 Will merge to 'next'.


* jc/push-to-checkout (2014-12-01) 2 commits
 - receive-pack: support push-to-checkout hook
 - receive-pack: refactor updateInstead codepath
 (this branch uses js/push-to-deploy.)

 Extending the js/push-to-deploy topic, the behaviour of "git push"
 when updating the working tree and the index with an update to the
 branch that is checked out can be tweaked by push-to-checkout hook.

 Needs docs.


* lh/send-email-hide-x-mailer (2014-12-04) 4 commits
 - SQUASH???
 - test/send-email: --[no-]xmailer tests
 - SQUASH???
 - send-email: add --[no-]xmailer option

 "git send-email" normally identifies itself via X-Mailer: header
 in the message it sends out.  A new command line flag allows the
 header to be squelched.


* nd/list-files (2014-12-01) 19 commits
 - list-files: -M aka diff-cached
 - list-files -F: show submodules with the new indicator '&'
 - list-files: add -F/--classify
 - list-files: show directories as well as files
 - list-files: do not show duplicate cached entries
 - list-files: sort output and remove duplicates
 - list-files: add -t back
 - list-files: add -1 short for --no-column
 - list-files: add -R/--recursive short for --max-depth=-1
 - list-files: -u does not imply showing stages
 - list-files: a user friendly version of ls-files and more
 - ls-files: support --max-depth
 - ls-files: add --column
 - ls-files: add --color to highlight file names
 - ls-files: buffer full item in strbuf before printing
 - ls_colors.c: highlight submodules like directories
 - ls_colors.c: add a function to color a file name
 - ls_colors.c: parse color.ls.* from config file
 - ls_colors.c: add $LS_COLORS parsing code

 A new "git list-files" Porcelain command, "ls-files" with bells and
 whistles.


* nd/ls-tree-pathspec (2014-12-01) 5 commits
 - t3102: style modernization
 - t3102: document that ls-tree does not yet support negated pathspec
 - ls-tree: disable negative pathspec because it's not supported
 - ls-tree: remove path filtering logic in show_tree
 - tree.c: update read_tree_recursive callback to pass strbuf as base

 "git ls-tree" does not support path selection based on negative
 pathspecs, but did not error out when negative pathspecs are given.

 Will merge to 'next'.


* rj/t0050-passes (2014-11-30) 1 commit
 - t0050-*.sh: mark the rename (case change) test as passing

 Will merge to 'next'.


* rt/for-each-ref-spell-tcl-as-Tcl (2014-11-30) 1 commit
 - for-each-ref: correct spelling of Tcl in option description

 Will merge to 'next'.


* sb/ref-transaction-reflog (2014-12-03) 2 commits
 - refs.c: rename transaction.updates to transaction.ref_updates
 - refs.c: rename the transaction functions
 (this branch uses sb/ref-transaction-unify-to-update.)

 Will be rerolled as a part of a larger series.


* ye/http-accept-language (2014-12-03) 2 commits
 - SQUASH???
 - http: send Accept-Language header if possible

 Breaks various people ($gmane/260903).


* jk/pack-bitmap (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-04 at eb457ad)
 + pack-bitmap: do not use gcc packed attribute

 Will merge to 'master'.


* nd/multiple-work-trees (2014-12-01) 34 commits
 - git-common-dir: make "modules/" per-working-directory directory
 - checkout: do not fail if target is an empty directory
 - t2025: add a test to make sure grafts is working from a linked checkout
 - checkout: don't require a work tree when checking out into a new one
 - git_path(): keep "info/sparse-checkout" per work-tree
 - count-objects: report unused files in $GIT_DIR/worktrees/...
 - gc: support prune --worktrees
 - gc: factor out gc.pruneexpire parsing code
 - gc: style change -- no SP before closing parenthesis
 - checkout: clean up half-prepared directories in --to mode
 - checkout: reject if the branch is already checked out elsewhere
 - prune: strategies for linked checkouts
 - checkout: support checking out into a new working directory
 - use new wrapper write_file() for simple file writing
 - wrapper.c: wrapper to open a file, fprintf then close
 - setup.c: support multi-checkout repo setup
 - setup.c: detect $GIT_COMMON_DIR check_repository_format_gently()
 - setup.c: convert check_repository_format_gently to use strbuf
 - setup.c: detect $GIT_COMMON_DIR in is_git_directory()
 - setup.c: convert is_git_directory() to use strbuf
 - git-stash: avoid hardcoding $GIT_DIR/logs/....
 - *.sh: avoid hardcoding $GIT_DIR/hooks/...
 - git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects
 - $GIT_COMMON_DIR: a new environment variable
 - commit: use SEQ_DIR instead of hardcoding "sequencer"
 - fast-import: use git_path() for accessing .git dir instead of get_git_dir()
 - reflog: avoid constructing .lock path with git_path
 - *.sh: respect $GIT_INDEX_FILE
 - git_path(): be aware of file relocation in $GIT_DIR
 - path.c: group git_path(), git_pathdup() and strbuf_git_path() together
 - path.c: rename vsnpath() to do_git_path()
 - git_snpath(): retire and replace with strbuf_git_path()
 - path.c: make get_pathname() call sites return const char *
 - path.c: make get_pathname() return strbuf instead of static buffer

 A replacement for contrib/workdir/git-new-workdir that does not
 rely on symbolic links and make sharing of objects and refs safer
 by making the borrowee and borrowers aware of each other.


* jc/unpack-trees-plug-leak (2014-11-17) 1 commit
  (merged to 'next' on 2014-12-04 at 9f1df30)
 + unpack_trees: plug leakage of o->result

 Will merge to 'master'.


* jk/colors (2014-12-09) 6 commits
  (merged to 'next' on 2014-12-09 at 802437b)
 + parse_color: drop COLOR_BACKGROUND macro
  (merged to 'next' on 2014-12-04 at 8d2e37b)
 + diff-highlight: allow configurable colors
 + parse_color: recognize "no$foo" to clear the $foo attribute
 + parse_color: support 24-bit RGB values
 + parse_color: refactor color storage
 + Merge branch 'jn/parse-config-slot' into jk/colors
 (this branch uses jk/colors-fix.)

 "diff-highlight" filter (in contrib/) allows its color output
 to be customized via configuration variables.

 Will merge to 'master'.


* jk/colors-fix (2014-11-20) 3 commits
  (merged to 'next' on 2014-12-04 at 0d97d69)
 + t4026: test "normal" color
 + config: fix parsing of "git config --get-color some.key -1"
 + docs: describe ANSI 256-color mode
 (this branch is used by jk/colors.)

 Will merge to 'master'.


* jk/lock-ref-sha1-basic-return-errors (2014-11-20) 1 commit
 - lock_ref_sha1_basic: do not die on locking errors

 Will merge to 'next'.


* jk/no-perl-tests (2014-11-18) 2 commits
  (merged to 'next' on 2014-12-04 at f166620)
 + t960[34]: mark cvsimport tests as requiring perl
 + t0090: mark add-interactive test with PERL prerequisite

 Some tests that depend on perl lacked PERL prerequisite to protect
 them, breaking build with NO_PERL configuration.

 Will merge to 'master'.


* jk/rebuild-perl-scripts-with-no-perl-seting-change (2014-11-18) 3 commits
  (merged to 'next' on 2014-12-04 at 27382d3)
 + Makefile: have python scripts depend on NO_PYTHON setting
 + Makefile: simplify by using SCRIPT_{PERL,SH}_GEN macros
 + Makefile: have perl scripts depend on NO_PERL setting

 The build procedure did not bother fixing perl and python scripts
 when NO_PERL and NO_PYTHON build-time configuration changed.

 Will merge to 'master'.


* mh/config-copy-string-from-git-path (2014-11-17) 1 commit
  (merged to 'next' on 2014-12-04 at 9c9518b)
 + cmd_config(): make a copy of path obtained from git_path()

 Will merge to 'master'.


* po/everyday-doc (2014-11-17) 1 commit
  (merged to 'next' on 2014-12-04 at 39d31fb)
 + Documentation: change "gitlink" typo in git-push

 Will merge to 'master'.


* ps/new-workdir-into-empty-directory (2014-12-03) 1 commit
 - git-new-workdir: don't fail if the target directory is empty

 Will merge to 'next'.


* rt/push-recurse-submodule-usage-string (2014-11-18) 1 commit
  (merged to 'next' on 2014-12-04 at c43e23c)
 + builtin/push.c: fix description of --recurse-submodules option

 Will merge to 'master'.


* sb/copy-fd-errno (2014-11-17) 1 commit
 - copy.c: make copy_fd preserve meaningful errno

 Will be rerolled as a part of a larger series.


* sb/log-ref-write-fd (2014-11-20) 1 commit
 - refs.c: add a function to append a reflog entry to a fd

 Will be rerolled as a part of a larger series.


* sb/ref-transaction-unify-to-update (2014-11-20) 2 commits
 - refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 - refs.c: make ref_transaction_create a wrapper for ref_transaction_update
 (this branch is used by sb/ref-transaction-reflog.)

 Code simplification.

 Will be rerolled as a part of a larger series.


* sv/doc-stripspace (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-04 at 32fd559)
 + Documentation/git-stripspace: add synopsis for --comment-lines

 Will merge to 'master'.


* sv/typofix-apply-error-message (2014-11-17) 1 commit
  (merged to 'next' on 2014-12-04 at de7547a)
 + apply: fix typo in an error message

 Will merge to 'master'.


* da/difftool-mergetool-simplify-reporting-status (2014-11-21) 5 commits
  (merged to 'next' on 2014-12-04 at c3c329f)
 + mergetools: stop setting $status in merge_cmd()
 + mergetool: simplify conditionals
 + difftool--helper: add explicit exit statement
 + mergetool--lib: remove use of $status global
 + mergetool--lib: remove no-op assignment to $status from setup_user_tool

 Code simplification.

 Will merge to 'master'.


* dw/shell-basename-dashdash-before-stripping-leading-dash-from-login (2014-11-25) 1 commit
 - git-sh-setup.sh: use dashdash with basename call

 Will merge to 'next'.


* jc/refer-to-t-readme-from-submitting-patches (2014-11-24) 2 commits
 - t/README: justify why "! grep foo" is sufficient
 - SubmittingPatches: refer to t/README for tests

 Will merge to 'next'.


* jc/t9001-modernise (2014-11-25) 5 commits
 - t9001: style modernisation phase #5
 - t9001: style modernisation phase #4
 - t9001: style modernisation phase #3
 - t9001: style modernisation phase #2
 - t9001: style modernisation phase #1
 (this branch uses pb/send-email-te.)


* js/t5000-dont-copy-bin-sh (2014-11-24) 1 commit
 - t5000 on Windows: do not mistake "sh.exe" as "sh"

 Will merge to 'next'.


* mg/add-ignore-errors (2014-11-21) 1 commit
 - add: ignore only ignored files

 Will merge to 'next'.


* mh/find-uniq-abbrev (2014-11-26) 1 commit
 - sha1_name: avoid unnecessary sha1 lookup in find_unique_abbrev

 Will merge to 'next'.


* mh/simplify-repack-without-refs (2014-11-25) 7 commits
 - sort_string_list(): rename to string_list_sort()
 - prune_remote(): iterate using for_each_string_list_item()
 - prune_remote(): rename local variable
 - repack_without_refs(): make the refnames argument a string_list
 - prune_remote(): sort delete_refs_list references en masse
 - prune_remote(): initialize both delete_refs lists in a single loop
 - prune_remote(): exit early if there are no stale references

 Will merge to 'next'.


* pb/am-message-id-footer (2014-11-25) 2 commits
 - git-am: add --message-id/--no-message-id
 - git-mailinfo: add --message-id

 Will merge to 'next'.


* pb/send-email-te (2014-11-25) 2 commits
 - git-send-email: add --transfer-encoding option
 - git-send-email: delay creation of MIME headers
 (this branch is used by jc/t9001-modernise.)

 Will merge to 'next'.


* pw/remote-set-url-fetch (2014-11-26) 1 commit
 - remote: add --fetch and --both options to set-url

 Still under discussion.


* rj/no-xopen-source-for-cygwin (2014-11-24) 1 commit
 - git-compat-util.h: don't define _XOPEN_SOURCE on cygwin

 Will merge to 'next'.


* sb/string-list (2014-12-04) 3 commits
 - string_list: remove string_list_insert_at_index() from its API
 - mailmap: use higher level string list functions
 - string_list: document string_list_(insert,lookup)

 Will merge to 'next'.


* sb/write-sha1-update-reflog (2014-11-24) 1 commit
 - refs.c: move reflog updates into its own function

 Moves a part of function around to add a helper that still only has
 one caller.  Need to see how this helps in a bigger picture.


* tb/config-core-filemode-check-on-broken-fs (2014-11-21) 1 commit
 - init-db: improve the filemode trustability check

 Will merge to 'next'.


* jk/approxidate-avoid-y-d-m-over-future-dates (2014-11-13) 2 commits
  (merged to 'next' on 2014-11-14 at 3c11a1b)
 + approxidate: allow ISO-like dates far in the future
 + pass TIME_DATE_NOW to approxidate future-check

 Traditionally we tried to avoid interpreting date strings given by
 the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
 used early November 2014 was taken as "October 12, 2014" because it
 is likely that a date in the future, December 10, is a mistake.

 Loosen this and do not tiebreak by future-ness of the date when

 (1) ISO-like format is used, and
 (2) the string can make sense interpreted as both y-m-d and y-d-m.

 Will cook in 'next'.


* mb/enable-lib-terminal-test-on-newer-darwin (2014-11-14) 1 commit
  (merged to 'next' on 2014-11-14 at b2aae27)
 + t/lib-terminal: allow TTY tests to run under recent Mac OS

 We probably should drop this ($gmane/259609).


* br/imap-send-verbosity (2014-11-05) 1 commit
  (merged to 'next' on 2014-11-12 at d9e58ec)
 + imap-send: use parse options API to determine verbosity
 (this branch is used by br/imap-send-via-libcurl.)

 Will cook in 'next'.


* br/imap-send-via-libcurl (2014-11-10) 1 commit
  (merged to 'next' on 2014-11-12 at 5327ab4)
 + git-imap-send: use libcurl for implementation
 (this branch uses br/imap-send-verbosity.)

 Will cook in 'next'.


* cc/interpret-trailers-more (2014-11-10) 4 commits
 - trailer: add test with an old style conflict block
 - trailer: reuse ignore_non_trailer() to ignore conflict lines
 - commit: make ignore_non_trailer() non static
 - Merge branch 'jc/conflict-hint' into cc/interpret-trailers-more
 (this branch uses jc/conflict-hint.)

 Will merge to 'next'.


* nd/lockfile-absolute (2014-11-03) 1 commit
  (merged to 'next' on 2014-11-06 at 68722a9)
 + lockfile.c: store absolute path

 The lockfile API can get confused which file to clean up when the
 process moved the $cwd after creating a lockfile.

 Will cook in 'next'.


* jc/merge-bases (2014-10-30) 2 commits
  (merged to 'next' on 2014-11-06 at 491e576)
 + get_merge_bases(): always clean-up object flags
 + bisect: clean flags after checking merge bases

 Will cook in 'next'.


* jc/strbuf-add-lines-avoid-sp-ht-sequence (2014-10-27) 1 commit
  (merged to 'next' on 2014-10-29 at 9167582)
 + strbuf_add_commented_lines(): avoid SP-HT sequence in commented lines

 The commented output used to blindly add a SP before the payload
 line, resulting in "# \t<indented text>\n" when the payload began
 with a HT.  Instead, produce "#\t<indented text>\n".

 Will cook in 'next'.


* nd/untracked-cache (2014-10-27) 19 commits
 - t7063: tests for untracked cache
 - update-index: test the system before enabling untracked cache
 - update-index: manually enable or disable untracked cache
 - status: enable untracked cache
 - untracked cache: mark index dirty if untracked cache is updated
 - untracked cache: print stats with $GIT_TRACE_UNTRACKED_STATS
 - untracked cache: avoid racy timestamps
 - read-cache.c: split racy stat test to a separate function
 - untracked cache: invalidate at index addition or removal
 - untracked cache: load from UNTR index extension
 - untracked cache: save to an index extension
 - untracked cache: don't open non-existent .gitignore
 - untracked cache: mark what dirs should be recursed/saved
 - untracked cache: record/validate dir mtime and reuse cached output
 - untracked cache: make a wrapper around {open,read,close}dir()
 - untracked cache: invalidate dirs recursively if .gitignore changes
 - untracked cache: initial untracked cache validation
 - untracked cache: record .gitignore information and dir hierarchy
 - dir.c: optionally compute sha-1 of a .gitignore file

 Comments?


* zk/grep-color-words (2014-10-27) 2 commits
  (merged to 'next' on 2014-10-28 at 4d0457c)
 + Revert "grep: fix match highlighting for combined patterns with context lines"
  (merged to 'next' on 2014-10-24 at 2d2f8f8)
 + grep: fix match highlighting for combined patterns with context lines

 rs/grep-color-words topic solves it in a different way.

 Will discard.


* jc/conflict-hint (2014-10-28) 4 commits
  (merged to 'next' on 2014-10-29 at 693250f)
 + merge & sequencer: turn "Conflicts:" hint into a comment
 + builtin/commit.c: extract ignore_non_trailer() helper function
 + merge & sequencer: unify codepaths that write "Conflicts:" hint
 + builtin/merge.c: drop a parameter that is never used
 (this branch is used by cc/interpret-trailers-more.)

 Unlike all the other hints given in the commit log editor, the list
 of conflicted paths were appended at the end without commented out.

 Will cook in 'next'.


* jc/diff-b-m (2014-10-23) 1 commit
  (merged to 'next' on 2014-10-28 at 4daedb1)
 + diff -B -M: fix output for "copy and then rewrite" case

 Fix long-standing bug in "diff -B -M" output.

 Will cook in 'next'.


* jc/checkout-local-track-report (2014-10-14) 1 commit
  (merged to 'next' on 2014-10-21 at f636a00)
 + checkout: report upstream correctly even with loosely defined branch.*.merge

 The report from "git checkout" on a branch that builds on another
 local branch by setting its branch.*.merge to branch name (not a
 full refname) incorrectly said that the upstream is gone.

 Will cook in 'next'.


* jc/clone-borrow (2014-10-15) 1 commit
  (merged to 'next' on 2014-10-21 at b76ea34)
 + clone: --dissociate option to mark that reference is only temporary

 Allow "git clone --reference" to be used more safely.

 Will cook in 'next'.

--------------------------------------------------
[Discarded]

* jt/timer-settime (2014-08-29) 6 commits
 . use timer_settime() for new platforms
 . autoconf: check for timer_settime()
 . autoconf: check for struct itimerspec
 . autoconf: check for struct sigevent
 . autoconf: check for struct timespec
 . autoconf: check for timer_t

 Was wanting for a reroll.


* rs/ref-transaction-reflog (2014-11-03) 15 commits
 . refs.c: allow deleting refs with a broken sha1
 . refs.c: remove lock_any_ref_for_update
 . refs.c: make unlock_ref/close_ref/commit_ref static
 . refs.c: rename log_ref_setup to create_reflog
 . reflog.c: use a reflog transaction when writing during expire
 . refs.c: allow multiple reflog updates during a single transaction
 . refs.c: only write reflog update if msg is non-NULL
 . refs.c: add a flag to allow reflog updates to truncate the log
 . refs.c: add a transaction function to append a reflog entry
 . copy.c: make copy_fd preserve meaningful errno
 . refs.c: add a function to append a reflog entry to a fd
 . refs.c: add a new update_type field to ref_update
 . refs.c: rename the transaction functions
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c make ref_transaction_create a wrapper to ref_transaction_update
 (this branch is used by rs/ref-transaction-rename and rs/ref-transaction-send-pack.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-rename (2014-11-07) 16 commits
 . refs.c: add an err argument to pack_refs
 . refs.c: make lock_packed_refs take an err argument
 . refs.c: make add_packed_ref return an error instead of calling die
 . refs.c: replace the onerr argument in update_ref with a strbuf err
 . refs.c: make the *_packed_refs functions static
 . refs.c: make repack_without_refs static
 . remote.c: use a transaction for deleting refs
 . refs.c: write updates to packed refs when a transaction has more than one ref
 . refs.c: move reflog updates into its own function
 . refs.c: rollback the lockfile before we die() in repack_without_refs
 . refs.c: update rename_ref to use a transaction
 . refs.c: add transaction support for renaming a reflog
 . refs.c: use a stringlist for repack_without_refs
 . refs.c: use packed refs when deleting refs during a transaction
 . refs.c: return error instead of dying when locking fails during transaction
 . refs.c: allow passing raw git_committer_info as email to _update_reflog
 (this branch is used by rs/ref-transaction-send-pack; uses rs/ref-transaction-reflog.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-send-pack (2014-11-07) 7 commits
 . refs.c: add an err argument to create_symref
 . refs.c: add an err argument to create_reflog
 . t5543-atomic-push.sh: add basic tests for atomic pushes
 . push.c: add an --atomic-push argument
 . receive-pack.c: use a single transaction when atomic-push is negotiated
 . send-pack.c: add an --atomic-push command line argument
 . receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses rs/ref-transaction-reflog and rs/ref-transaction-rename.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* sb/simplify-repack-without-refs (2014-11-20) 1 commit
 . refs.c: use a string_list for repack_without_refs

^ permalink raw reply	[relevance 3%]

* What's cooking in git.git (Dec 2014, #03; Mon, 15)
@ 2014-12-15 20:40  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-12-15 20:40 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

The 'next' branch has been rewound and rebuilt on top of 2.2; I
expect this to be a short and light cycle that would not add too
many new things.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[Graduated to "master"]

* da/difftool-mergetool-simplify-reporting-status (2014-11-21) 5 commits
  (merged to 'next' on 2014-12-04 at c3c329f)
 + mergetools: stop setting $status in merge_cmd()
 + mergetool: simplify conditionals
 + difftool--helper: add explicit exit statement
 + mergetool--lib: remove use of $status global
 + mergetool--lib: remove no-op assignment to $status from setup_user_tool

 Code simplification.


* jc/unpack-trees-plug-leak (2014-11-17) 1 commit
  (merged to 'next' on 2014-12-04 at 9f1df30)
 + unpack_trees: plug leakage of o->result


* jk/colors-fix (2014-11-20) 3 commits
  (merged to 'next' on 2014-12-04 at 0d97d69)
 + t4026: test "normal" color
 + config: fix parsing of "git config --get-color some.key -1"
 + docs: describe ANSI 256-color mode
 (this branch is used by jk/colors.)


* jk/no-perl-tests (2014-11-18) 2 commits
  (merged to 'next' on 2014-12-04 at f166620)
 + t960[34]: mark cvsimport tests as requiring perl
 + t0090: mark add-interactive test with PERL prerequisite

 Some tests that depend on perl lacked PERL prerequisite to protect
 them, breaking build with NO_PERL configuration.


* jk/pack-bitmap (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-04 at eb457ad)
 + pack-bitmap: do not use gcc packed attribute


* jk/push-simple (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-04 at 00785c7)
 + push: truly use "simple" as default, not "upstream"

 Git 2.0 was supposed to make the "simple" mode for the default of
 "git push", but it didn't.


* jk/rebuild-perl-scripts-with-no-perl-seting-change (2014-11-18) 3 commits
  (merged to 'next' on 2014-12-04 at 27382d3)
 + Makefile: have python scripts depend on NO_PYTHON setting
 + Makefile: simplify by using SCRIPT_{PERL,SH}_GEN macros
 + Makefile: have perl scripts depend on NO_PERL setting

 The build procedure did not bother fixing perl and python scripts
 when NO_PERL and NO_PYTHON build-time configuration changed.


* mh/config-copy-string-from-git-path (2014-11-17) 1 commit
  (merged to 'next' on 2014-12-04 at 9c9518b)
 + cmd_config(): make a copy of path obtained from git_path()


* po/everyday-doc (2014-11-17) 1 commit
  (merged to 'next' on 2014-12-04 at 39d31fb)
 + Documentation: change "gitlink" typo in git-push


* rt/push-recurse-submodule-usage-string (2014-11-18) 1 commit
  (merged to 'next' on 2014-12-04 at c43e23c)
 + builtin/push.c: fix description of --recurse-submodules option


* sv/typofix-apply-error-message (2014-11-17) 1 commit
  (merged to 'next' on 2014-12-04 at de7547a)
 + apply: fix typo in an error message

--------------------------------------------------
[New Topics]

* jk/test-asan (2014-12-11) 1 commit
  (merged to 'next' on 2014-12-15 at d24cb92)
 + t: support clang/gcc AddressSanitizer

 Will merge to 'master'.


* nd/split-index (2014-12-11) 1 commit
  (merged to 'next' on 2014-12-15 at ed6490c)
 + index-format.txt: add a missing closing quote

 A typofix to the documentation of a feature already in the release.

 Will merge to 'master'.


* ch/new-gpg-drops-rfc-1991 (2014-12-12) 4 commits
  (merged to 'next' on 2014-12-15 at 32d7d50)
 + tests: squelch noise from GPG machinery set-up
 + tests: replace binary GPG keyrings with ASCII-armored keys
 + tests: skip RFC1991 tests for gnupg 2.1
 + tests: create gpg homedir on the fly

 Recent GPG changes the keyring format and drops support for RFC1991
 formatted signatures, breaking our existing tests.

 Will merge to 'master'.


* jg/prompt-localize-temporary (2014-12-12) 1 commit
  (merged to 'next' on 2014-12-15 at bb9cac9)
 + git-prompt.sh: make $f local to __git_eread()

 "git-prompt" (in contrib/) used a variable from the global scope,
 possibly contaminating end-user's namespace.

 Will merge to 'master'.


* jk/strbuf-doc-to-header (2014-12-12) 4 commits
 - strbuf.h: reorganize api function grouping headers
 - strbuf.h: format asciidoc code blocks as 4-space indent
 - strbuf.h: drop asciidoc list formatting from API docs
 - strbuf: migrate api-strbuf.txt documentation to strbuf.h

 Resolve the "doc vs header" to favor the latter.

 Expecting to be rerolled.


* mh/reflog-expire (2014-12-12) 24 commits
 - refs.c: let fprintf handle the formatting
 - refs.c: don't expose the internal struct ref_lock in the header file
 - lock_any_ref_for_update(): inline function
 - refs.c: remove unlock_ref/close_ref/commit_ref from the refs api
 - reflog_expire(): new function in the reference API
 - expire_reflog(): treat the policy callback data as opaque
 - Move newlog and last_kept_sha1 to "struct expire_reflog_cb"
 - expire_reflog(): move rewrite to flags argument
 - expire_reflog(): move verbose to flags argument
 - expire_reflog(): pass flags through to expire_reflog_ent()
 - struct expire_reflog_cb: a new callback data type
 - Rename expire_reflog_cb to expire_reflog_policy_cb
 - expire_reflog(): move updateref to flags argument
 - expire_reflog(): move dry_run to flags argument
 - expire_reflog(): add a "flags" argument
 - expire_reflog(): extract two policy-related functions
 - Extract function should_expire_reflog_ent()
 - expire_reflog(): use a lock_file for rewriting the reflog file
 - expire_reflog(): return early if the reference has no reflog
 - expire_reflog(): rename "ref" parameter to "refname"
 - expire_reflog(): it's not an each_ref_fn anymore
 - refs.c: add a function to append a reflog entry to a fd
 - refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 - refs.c: make ref_transaction_create a wrapper for ref_transaction_update

 Restructure "reflog expire" to fit the reflogs better with the
 recently updated ref API.

 Looked reasonable (except that ome shortlog entries stood out like
 a sore thumb).


* po/doc-core-ignorestat (2014-12-12) 1 commit
 - doc: core.ignoreStat clarify the --assume-unchanged effect

 Expecting a reroll.


* rs/use-strbuf-complete-line (2014-12-12) 1 commit
  (merged to 'next' on 2014-12-15 at d6426a0)
 + use strbuf_complete_line() for adding a newline if needed

 Will merge to 'master'.


* jk/add-i-read-error (2014-12-15) 1 commit
 - add--interactive: leave main loop on read error

 "git add -i" did not notice when the interactive command input
 stream went away and kept asking.

 Will merge to 'next'.


* pd/completion-filenames-fix (2014-12-15) 1 commit
 - Update documentation occurrences of filename .sh

 The top-of-the-file instruction for completion scripts (in contrib/)
 did not name the files correctly.

 Will merge to 'next'.


* rd/send-email-2047-fix (2014-12-15) 2 commits
 - send-email: handle adjacent RFC 2047-encoded words properly
 - send-email: align RFC 2047 decoding more closely with the spec

 "git send-email" did not handle RFC 2047 encoded headers quite
 right.

 Will merge to 'next'.

--------------------------------------------------
[Stalled]

* pw/remote-set-url-fetch (2014-11-26) 1 commit
 - remote: add --fetch and --both options to set-url

 Expecting a reroll.


* ye/http-accept-language (2014-12-03) 2 commits
 . SQUASH???
 . http: send Accept-Language header if possible

 Breaks various people ($gmane/260903).


* ms/submodule-update-config-doc (2014-11-03) 1 commit
 - submodule: clarify documentation for update subcommand

 Needs a reroll ($gmane/259037).


* je/quiltimport-no-fuzz (2014-10-21) 2 commits
 - git-quiltimport: flip the default not to allow fuzz
 - git-quiltimport.sh: allow declining fuzz with --exact option

 "quiltimport" drove "git apply" always with -C1 option to reduce
 context of the patch in order to give more chance to somewhat stale
 patches to apply.  Add an "--exact" option to disable, and also
 "-C$n" option to customize this behaviour.  The top patch
 optionally flips the default to "--exact".

 Tired of waiting for an Ack; will discard.


* jc/push-cert-hmac-optim (2014-09-25) 2 commits
 - receive-pack: truncate hmac early and convert only necessary bytes
 - sha1_to_hex: split out "hex-format n bytes" helper and use it

 This is "we could do this if we wanted to", not "we measured and it
 improves performance critical codepath".

 Will perhaps drop.


* mt/patch-id-stable (2014-06-10) 1 commit
 - patch-id: change default to stable

 Teaches "git patch-id" to compute the patch ID that does not change
 when the files in a single patch is reordered. As this new algorithm
 is backward incompatible, the last bit to flip it to be the default
 is left out of 'master' for now.

 Nobody seems to be jumping up & down requesting this last step,
 which makes the result somewhat backward incompatible.
 Will perhaps drop.


* tr/remerge-diff (2014-11-10) 9 commits
 - t4213: avoid "|" in sed regexp
 - log --remerge-diff: show what the conflict resolution changed
 - name-hash: allow dir hashing even when !ignore_case
 - merge-recursive: allow storing conflict hunks in index
 - merge_diff_mode: fold all merge diff variants into an enum
 - combine-diff: do not pass revs->dense_combined_merges redundantly
 - merge-recursive: -Xindex-only to leave worktree unchanged
 - merge-recursive: internal flag to avoid touching the worktree
 - merge-recursive: remove dead conditional in update_stages()

 "log -p" output learns a new way to let users inspect a merge
 commit by showing the differences between the automerged result
 with conflicts the person who recorded the merge would have seen
 and the final conflict resolution that was recorded in the merge.

 Waiting for a reroll ($gmane/256591).


* hv/submodule-config (2014-11-11) 4 commits
 - do not die on error of parsing fetchrecursesubmodules option
 - use new config API for worktree configurations of submodules
 - extract functions for submodule config set and lookup
 - implement submodule config cache for lookup of submodule names

 Kicked back to 'pu' per request ($gmane/255610).


* ab/add-interactive-show-diff-func-name (2014-05-12) 2 commits
 - SQUASH??? git-add--interactive: Preserve diff heading when splitting hunks
 - git-add--interactive: Preserve diff heading when splitting hunks

 Waiting for a reroll.


* jn/gitweb-utf8-in-links (2014-05-27) 1 commit
 - gitweb: Harden UTF-8 handling in generated links

 $gmane/250758?


* ss/userdiff-update-csharp-java (2014-06-02) 2 commits
 - userdiff: support Java try keyword
 - userdiff: support C# async methods and correct C# keywords

 Reviews sent; waiting for a response.


* bg/rebase-off-of-previous-branch (2014-04-16) 1 commit
 - git-rebase: print name of rev when using shorthand

 Teach "git rebase -" to report the concrete name of the branch
 (i.e. the previous one).

 But it stops short and does not do the same for "git rebase @{-1}".
 Expecting a reroll.


* rb/merge-prepare-commit-msg-hook (2014-01-10) 4 commits
 - merge: drop unused arg from abort_commit method signature
 - merge: make prepare_to_commit responsible for write_merge_state
 - t7505: ensure cleanup after hook blocks merge
 - t7505: add missing &&

 Expose more merge states (e.g. $GIT_DIR/MERGE_MODE) to hooks that
 run during "git merge".  The log message stresses too much on one
 hook, prepare-commit-msg, but it would equally apply to other hooks
 like post-merge, I think.

 Waiting for a reroll.


* jc/graph-post-root-gap (2013-12-30) 3 commits
 - WIP: document what we want at the end
 - graph: remove unused code a bit
 - graph: stuff the current commit into graph->columns[]

 This was primarily a RFH ($gmane/239580).


* tg/perf-lib-test-perf-cleanup (2013-09-19) 2 commits
 - perf-lib: add test_perf_cleanup target
 - perf-lib: split starting the test from the execution

 Add test_perf_cleanup shell function to the perf suite, that allows
 the script writers to define a test with a clean-up action.

 Will hold.


* jc/show-branch (2014-03-24) 5 commits
 - show-branch: use commit slab to represent bitflags of arbitrary width
 - show-branch.c: remove "all_mask"
 - show-branch.c: abstract out "flags" operation
 - show-branch.c: lift all_mask/all_revs to a global static
 - show-branch.c: update comment style

 Waiting for the final step to lift the hard-limit before sending it out.

--------------------------------------------------
[Cooking]

* dm/compat-s-ifmt-for-zos (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-15 at 0eb2fe6)
 + compat: convert modes to use portable file type values

 Long overdue departure from the assumption that S_IFMT is shared by
 everybody made in 2005.

 Will merge to 'master'.


* jk/credential-quit (2014-12-04) 2 commits
  (merged to 'next' on 2014-12-15 at 4cfd999)
 + prompt: respect GIT_TERMINAL_PROMPT to disable terminal prompts
 + credential: let helpers tell us to quit

 Credential helpers are asked in turn until one of them give
 positive response, which is cumbersome to turn off when you need to
 run Git in an automated setting.  The credential helper interface
 learned to allow a helper to say "stop, don't ask other helpers."
 Also GIT_TERMINAL_PROMPT environment can be set to false to disable
 our built-in prompt mechanism for passwords.

 Will merge to 'master'.


* mg/branch-d-m-f (2014-12-09) 2 commits
  (merged to 'next' on 2014-12-15 at 8366f2c)
 + branch: allow -f with -m and -d
 + t3200-branch: test -M

 "git branch -d" (delete) and "git branch -m" (move) learned to
 honor "-f" (force) flag; unlike many other subcommands, the way to
 force these have been with separate "-D/-M" options, which was
 inconsistent.

 Will merge to 'master'.


* mg/doc-check-ignore-tracked-are-not-ignored (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-15 at c50f748)
 + check-ignore: clarify treatment of tracked files

 Will merge to 'master'.


* rt/completion-tag (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-15 at b03ee39)
 + completion: add git-tag options

 Will merge to 'master'.


* jk/for-each-reflog-ent-reverse (2014-12-05) 2 commits
  (merged to 'next' on 2014-12-15 at de71f08)
 + for_each_reflog_ent_reverse: turn leftover check into assertion
 + for_each_reflog_ent_reverse: fix newlines on block boundaries

 The code that reads the reflog from the newer to the older entries
 did not handle an entry that crosses a boundary of block it uses to
 read them correctly.

 Will merge to 'master'.


* po/doc-assume-unchanged (2014-12-09) 2 commits
  (merged to 'next' on 2014-12-15 at 646e77e)
 + gitignore.txt: do not suggest assume-unchanged
 + doc: make clear --assume-unchanged's user contract

 Fixes long-standing misunderstanding of what assume-unchanged is
 about.  Some text near what is removed by the bottom patch may also
 have to be removed.

 Will merge to 'master'.


* tb/t0027-eol-conversion (2014-12-05) 1 commit
  (merged to 'next' on 2014-12-15 at ba24e75)
 + t0027: check the eol conversion warnings

 Will merge to 'master'.


* jk/always-allow-large-packets (2014-12-10) 1 commit
  (merged to 'next' on 2014-12-15 at c3fb2c8)
 + pkt-line: allow writing of LARGE_PACKET_MAX buffers

 "git push" and "git fetch" did not communicate an overlong refname
 correctly.

 Will merge to 'master'.


* jk/commit-date-approxidate (2014-12-11) 2 commits
  (merged to 'next' on 2014-12-15 at 047530e)
 + commit: always populate GIT_AUTHOR_* variables
 + commit: loosen ident checks when generating template

 Recent update to "git commit" broke amending an existing commit
 with bogus author/committer lines without a valid e-mail address.

 Will merge to 'master'.


* jk/read-packed-refs-without-path-max (2014-12-10) 3 commits
  (merged to 'next' on 2014-12-15 at c6d6f56)
 + read_packed_refs: use skip_prefix instead of static array
 + read_packed_refs: pass strbuf to parse_ref_line
 + read_packed_refs: use a strbuf for reading lines

 Git did not correctly read an overlong refname from a packed refs
 file.

 Will merge to 'master'.


* jn/doc-api-errors (2014-12-04) 1 commit
 - doc: document error handling functions and conventions

 For discussion.


* js/fsck-tag-validation (2014-12-09) 2 commits
  (merged to 'next' on 2014-12-15 at 455f26c)
 + index-pack: terminate object buffers with NUL
 + fsck: properly bound "invalid tag name" error message

 New tag object format validation added in 2.2 showed garbage
 after a tagname it reported in its error message.

 Will merge to 'master'.


* js/test-hashmap-squelch-gcc (2014-12-09) 1 commit
  (merged to 'next' on 2014-12-15 at a8da691)
 + test-hashmap: squelch gcc compiler warning

 Will merge to 'master'.


* ok/rebase-i-count-todo (2014-12-10) 1 commit
  (merged to 'next' on 2014-12-15 at 4a1f7ed)
 + Show number of TODO items for interactive rebase

 Will merge to 'master'.


* rw/apply-does-not-take-ignore-date (2014-12-09) 1 commit
  (merged to 'next' on 2014-12-15 at ded2f99)
 + git-am.txt: --ignore-date flag is not passed to git-apply

 Will merge to 'master'.


* jc/exec-cmd-system-path-leak-fix (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-15 at f926ee5)
 + system_path(): always return free'able memory to the caller

 The function sometimes returned a non-freeable memory and some
 other times returned a piece of memory that must be freed.

 Will merge to 'master'.


* jc/hook-cleanup (2014-12-01) 1 commit
  (merged to 'next' on 2014-12-15 at f5759d0)
 + run-command.c: retire unused run_hook_with_custom_index()

 Remove unused code.

 Will merge to 'master'.


* jn/rerere-fail-on-auto-update-failure (2014-12-03) 2 commits
 - SQUASH???
 - rerere: error out on autoupdate failure

 Will be rerolled as a part of a larger series.


* js/push-to-deploy (2014-11-30) 2 commits
  (merged to 'next' on 2014-12-15 at ef8c99f)
 + t5516: more tests for receive.denyCurrentBranch=updateInstead
 + receive-pack: add another option for receive.denyCurrentBranch
 (this branch is used by jc/push-to-checkout.)

 "git push" into a repository with a working tree normally refuses
 to modify the branch that is checked out.  The command learned to
 optionally do an equivalent of "git reset --hard" only when there
 is no change to the working tree and the index instead, which would
 be useful to "deploy" by pushing into a repository.

 Will merge to 'master'.


* jc/push-to-checkout (2014-12-01) 2 commits
 - receive-pack: support push-to-checkout hook
 - receive-pack: refactor updateInstead codepath
 (this branch uses js/push-to-deploy.)

 Extending the js/push-to-deploy topic, the behaviour of "git push"
 when updating the working tree and the index with an update to the
 branch that is checked out can be tweaked by push-to-checkout hook.

 Needs docs.


* lh/send-email-hide-x-mailer (2014-12-11) 4 commits
 - SQUASH???
 - test/send-email: --[no-]xmailer tests
 - SQUASH???
 - send-email: add --[no-]xmailer option

 "git send-email" normally identifies itself via X-Mailer: header
 in the message it sends out.  A new command line flag allows the
 header to be squelched.

 Will merge to 'next' after squashing the fixups.


* nd/list-files (2014-12-01) 19 commits
 - list-files: -M aka diff-cached
 - list-files -F: show submodules with the new indicator '&'
 - list-files: add -F/--classify
 - list-files: show directories as well as files
 - list-files: do not show duplicate cached entries
 - list-files: sort output and remove duplicates
 - list-files: add -t back
 - list-files: add -1 short for --no-column
 - list-files: add -R/--recursive short for --max-depth=-1
 - list-files: -u does not imply showing stages
 - list-files: a user friendly version of ls-files and more
 - ls-files: support --max-depth
 - ls-files: add --column
 - ls-files: add --color to highlight file names
 - ls-files: buffer full item in strbuf before printing
 - ls_colors.c: highlight submodules like directories
 - ls_colors.c: add a function to color a file name
 - ls_colors.c: parse color.ls.* from config file
 - ls_colors.c: add $LS_COLORS parsing code

 A new "git list-files" Porcelain command, "ls-files" with bells and
 whistles.


* nd/ls-tree-pathspec (2014-12-01) 5 commits
  (merged to 'next' on 2014-12-15 at 8da6e09)
 + t3102: style modernization
 + t3102: document that ls-tree does not yet support negated pathspec
 + ls-tree: disable negative pathspec because it's not supported
 + ls-tree: remove path filtering logic in show_tree
 + tree.c: update read_tree_recursive callback to pass strbuf as base

 "git ls-tree" does not support path selection based on negative
 pathspecs, but did not error out when negative pathspecs are given.

 Will merge to 'master'.


* rj/t0050-passes (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-15 at f56c339)
 + t0050-*.sh: mark the rename (case change) test as passing

 Will merge to 'master'.


* rt/for-each-ref-spell-tcl-as-Tcl (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-15 at c0fcefb)
 + for-each-ref: correct spelling of Tcl in option description

 Will merge to 'master'.


* sb/ref-transaction-reflog (2014-12-03) 2 commits
 . refs.c: rename transaction.updates to transaction.ref_updates
 . refs.c: rename the transaction functions
 (this branch uses sb/ref-transaction-unify-to-update.)

 Will be rerolled as a part of a larger series.


* nd/multiple-work-trees (2014-12-01) 34 commits
 - git-common-dir: make "modules/" per-working-directory directory
 - checkout: do not fail if target is an empty directory
 - t2025: add a test to make sure grafts is working from a linked checkout
 - checkout: don't require a work tree when checking out into a new one
 - git_path(): keep "info/sparse-checkout" per work-tree
 - count-objects: report unused files in $GIT_DIR/worktrees/...
 - gc: support prune --worktrees
 - gc: factor out gc.pruneexpire parsing code
 - gc: style change -- no SP before closing parenthesis
 - checkout: clean up half-prepared directories in --to mode
 - checkout: reject if the branch is already checked out elsewhere
 - prune: strategies for linked checkouts
 - checkout: support checking out into a new working directory
 - use new wrapper write_file() for simple file writing
 - wrapper.c: wrapper to open a file, fprintf then close
 - setup.c: support multi-checkout repo setup
 - setup.c: detect $GIT_COMMON_DIR check_repository_format_gently()
 - setup.c: convert check_repository_format_gently to use strbuf
 - setup.c: detect $GIT_COMMON_DIR in is_git_directory()
 - setup.c: convert is_git_directory() to use strbuf
 - git-stash: avoid hardcoding $GIT_DIR/logs/....
 - *.sh: avoid hardcoding $GIT_DIR/hooks/...
 - git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects
 - $GIT_COMMON_DIR: a new environment variable
 - commit: use SEQ_DIR instead of hardcoding "sequencer"
 - fast-import: use git_path() for accessing .git dir instead of get_git_dir()
 - reflog: avoid constructing .lock path with git_path
 - *.sh: respect $GIT_INDEX_FILE
 - git_path(): be aware of file relocation in $GIT_DIR
 - path.c: group git_path(), git_pathdup() and strbuf_git_path() together
 - path.c: rename vsnpath() to do_git_path()
 - git_snpath(): retire and replace with strbuf_git_path()
 - path.c: make get_pathname() call sites return const char *
 - path.c: make get_pathname() return strbuf instead of static buffer

 A replacement for contrib/workdir/git-new-workdir that does not
 rely on symbolic links and make sharing of objects and refs safer
 by making the borrowee and borrowers aware of each other.


* jk/colors (2014-12-09) 6 commits
  (merged to 'next' on 2014-12-15 at 20b045f)
 + parse_color: drop COLOR_BACKGROUND macro
 + diff-highlight: allow configurable colors
 + parse_color: recognize "no$foo" to clear the $foo attribute
 + parse_color: support 24-bit RGB values
 + parse_color: refactor color storage
 + Merge branch 'jn/parse-config-slot' into jk/colors

 "diff-highlight" filter (in contrib/) allows its color output
 to be customized via configuration variables.

 Will merge to 'master'.


* jk/lock-ref-sha1-basic-return-errors (2014-11-20) 1 commit
  (merged to 'next' on 2014-12-15 at c48b110)
 + lock_ref_sha1_basic: do not die on locking errors

 Correct an API anomaly.

 Will merge to 'master'.


* ps/new-workdir-into-empty-directory (2014-12-03) 1 commit
  (merged to 'next' on 2014-12-15 at 0787b56)
 + git-new-workdir: don't fail if the target directory is empty

 "git new-workdir" (in contrib/) can be used to populate an empty
 and existing directory now.

 Will merge to 'master'.


* sb/copy-fd-errno (2014-11-17) 1 commit
 - copy.c: make copy_fd preserve meaningful errno

 Will be rerolled as a part of a larger series.


* sv/doc-stripspace (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-15 at e86f8ba)
 + Documentation/git-stripspace: add synopsis for --comment-lines

 Will merge to 'master'.


* dw/shell-basename-dashdash-before-stripping-leading-dash-from-login (2014-11-25) 1 commit
  (merged to 'next' on 2014-12-15 at 42937b7)
 + git-sh-setup.sh: use dashdash with basename call

 Will merge to 'master'.


* jc/refer-to-t-readme-from-submitting-patches (2014-11-24) 2 commits
  (merged to 'next' on 2014-12-15 at 0e88699)
 + t/README: justify why "! grep foo" is sufficient
 + SubmittingPatches: refer to t/README for tests

 Will merge to 'master'.


* jc/t9001-modernise (2014-11-25) 5 commits
 - t9001: style modernisation phase #5
 - t9001: style modernisation phase #4
 - t9001: style modernisation phase #3
 - t9001: style modernisation phase #2
 - t9001: style modernisation phase #1
 (this branch uses pb/send-email-te.)


* js/t5000-dont-copy-bin-sh (2014-11-24) 1 commit
  (merged to 'next' on 2014-12-15 at 65ffd05)
 + t5000 on Windows: do not mistake "sh.exe" as "sh"

 Will merge to 'master'.


* mg/add-ignore-errors (2014-11-21) 1 commit
  (merged to 'next' on 2014-12-15 at 3834789)
 + add: ignore only ignored files

 "git add --ignore-errors ..." did not ignore an error to
 give a file that did not exist.

 Will merge to 'master'.


* mh/find-uniq-abbrev (2014-11-26) 1 commit
  (merged to 'next' on 2014-12-15 at e3b2b62)
 + sha1_name: avoid unnecessary sha1 lookup in find_unique_abbrev

 The code to abbreviate an object name to its short unique prefix
 has been optimized when no abbreviation was requested.

 Will merge to 'master'.


* mh/simplify-repack-without-refs (2014-11-25) 7 commits
  (merged to 'next' on 2014-12-15 at 351e03e)
 + sort_string_list(): rename to string_list_sort()
 + prune_remote(): iterate using for_each_string_list_item()
 + prune_remote(): rename local variable
 + repack_without_refs(): make the refnames argument a string_list
 + prune_remote(): sort delete_refs_list references en masse
 + prune_remote(): initialize both delete_refs lists in a single loop
 + prune_remote(): exit early if there are no stale references

 "git remote update --prune" to drop many refs has been optimized.

 Will merge to 'master'.


* pb/am-message-id-footer (2014-11-25) 2 commits
  (merged to 'next' on 2014-12-15 at b44b6bd)
 + git-am: add --message-id/--no-message-id
 + git-mailinfo: add --message-id

 "git am" learned "--message-id" option to copy the message ID of
 the incoming e-mail to the log message of resulting commit.

 Will merge to 'master'.


* pb/send-email-te (2014-11-25) 2 commits
  (merged to 'next' on 2014-12-15 at 38c2810)
 + git-send-email: add --transfer-encoding option
 + git-send-email: delay creation of MIME headers
 (this branch is used by jc/t9001-modernise.)

 "git send-email" learned "--transfer-encoding" option to force
 a non-fault Content-Transfer-Encoding header (e.g. base64).

 Will merge to 'master'.


* rj/no-xopen-source-for-cygwin (2014-11-24) 1 commit
  (merged to 'next' on 2014-12-15 at 6e8e9ff)
 + git-compat-util.h: don't define _XOPEN_SOURCE on cygwin

 Avoid compilation warnings on recent gcc toolchain on Cygwin.

 Will merge to 'master'.


* sb/string-list (2014-12-04) 3 commits
  (merged to 'next' on 2014-12-15 at 8bb8ddd)
 + string_list: remove string_list_insert_at_index() from its API
 + mailmap: use higher level string list functions
 + string_list: document string_list_(insert,lookup)

 API simplification.

 Will merge to 'master'.


* sb/write-sha1-update-reflog (2014-11-24) 1 commit
 . refs.c: move reflog updates into its own function

 Moves a part of function around to add a helper that still only has
 one caller.  Need to see how this helps in a bigger picture.


* tb/config-core-filemode-check-on-broken-fs (2014-11-21) 1 commit
  (merged to 'next' on 2014-12-15 at 3e5490b)
 + init-db: improve the filemode trustability check

 Some filesystems assign filemodes in a strange way, fooling then
 automatic "filemode trustability" check done during a new
 repository creation.

 Will merge to 'master'.


* jk/approxidate-avoid-y-d-m-over-future-dates (2014-11-13) 2 commits
  (merged to 'next' on 2014-12-15 at 397e986)
 + approxidate: allow ISO-like dates far in the future
 + pass TIME_DATE_NOW to approxidate future-check

 Traditionally we tried to avoid interpreting date strings given by
 the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
 used early November 2014 was taken as "October 12, 2014" because it
 is likely that a date in the future, December 10, is a mistake.

 Loosen this and do not tiebreak by future-ness of the date when

 (1) ISO-like format is used, and
 (2) the string can make sense interpreted as both y-m-d and y-d-m.

 Will cook in 'next'.


* br/imap-send-verbosity (2014-11-05) 1 commit
  (merged to 'next' on 2014-12-15 at 504af0b)
 + imap-send: use parse options API to determine verbosity
 (this branch is used by br/imap-send-via-libcurl.)

 Will cook in 'next'.


* br/imap-send-via-libcurl (2014-11-10) 1 commit
  (merged to 'next' on 2014-12-15 at 90db637)
 + git-imap-send: use libcurl for implementation
 (this branch uses br/imap-send-verbosity.)

 Newer libCurl knows how to talk IMAP; "git imap-send" has been
 updated to use this instead of a hand-rolled OpenSSL calls.

 Will cook in 'next'.


* cc/interpret-trailers-more (2014-11-10) 4 commits
  (merged to 'next' on 2014-12-15 at 77f6c6a)
 + trailer: add test with an old style conflict block
 + trailer: reuse ignore_non_trailer() to ignore conflict lines
 + commit: make ignore_non_trailer() non static
 + Merge branch 'jc/conflict-hint' into cc/interpret-trailers-more
 (this branch uses jc/conflict-hint.)

 "git interpret-trailers" learned to properly handle the
 "Conflicts:" block at the end.

 Will merge to 'master'.


* nd/lockfile-absolute (2014-11-03) 1 commit
  (merged to 'next' on 2014-12-15 at 34db9af)
 + lockfile.c: store absolute path

 The lockfile API can get confused which file to clean up when the
 process moved the $cwd after creating a lockfile.

 Will cook in 'next'.


* jc/merge-bases (2014-10-30) 2 commits
  (merged to 'next' on 2014-12-15 at cac279e)
 + get_merge_bases(): always clean-up object flags
 + bisect: clean flags after checking merge bases

 The get_merge_bases*() API was easy to misuse by careless
 copy&paste coders, leaving object flags tainted in the commits that
 needed to be traversed.

 Will cook in 'next'.


* jc/strbuf-add-lines-avoid-sp-ht-sequence (2014-10-27) 1 commit
  (merged to 'next' on 2014-12-15 at b499889)
 + strbuf_add_commented_lines(): avoid SP-HT sequence in commented lines

 The commented output used to blindly add a SP before the payload
 line, resulting in "# \t<indented text>\n" when the payload began
 with a HT.  Instead, produce "#\t<indented text>\n".

 Will cook in 'next'.


* nd/untracked-cache (2014-12-15) 24 commits
 - SQUASH???
 - untracked cache: guard and disable on system changes
 - mingw32: add uname()
 - t7063: tests for untracked cache
 - update-index: test the system before enabling untracked cache
 - update-index: manually enable or disable untracked cache
 - status: enable untracked cache
 - untracked-cache: temporarily disable with $GIT_DISABLE_UNTRACKED_CACHE
 - untracked cache: mark index dirty if untracked cache is updated
 - untracked cache: print stats with $GIT_TRACE_UNTRACKED_STATS
 - untracked cache: avoid racy timestamps
 - read-cache.c: split racy stat test to a separate function
 - untracked cache: invalidate at index addition or removal
 - untracked cache: load from UNTR index extension
 - untracked cache: save to an index extension
 - ewah: add convenient wrapper ewah_serialize_strbuf()
 - untracked cache: don't open non-existent .gitignore
 - untracked cache: mark what dirs should be recursed/saved
 - untracked cache: record/validate dir mtime and reuse cached output
 - untracked cache: make a wrapper around {open,read,close}dir()
 - untracked cache: invalidate dirs recursively if .gitignore changes
 - untracked cache: initial untracked cache validation
 - untracked cache: record .gitignore information and dir hierarchy
 - dir.c: optionally compute sha-1 of a .gitignore file

 Comments?


* jc/conflict-hint (2014-10-28) 4 commits
  (merged to 'next' on 2014-12-15 at b72475f)
 + merge & sequencer: turn "Conflicts:" hint into a comment
 + builtin/commit.c: extract ignore_non_trailer() helper function
 + merge & sequencer: unify codepaths that write "Conflicts:" hint
 + builtin/merge.c: drop a parameter that is never used
 (this branch is used by cc/interpret-trailers-more.)

 Unlike all the other hints given in the commit log editor, the list
 of conflicted paths were appended at the end without commented out.

 Will cook in 'next'.


* jc/diff-b-m (2014-10-23) 1 commit
  (merged to 'next' on 2014-12-15 at 59c6636)
 + diff -B -M: fix output for "copy and then rewrite" case

 Fix long-standing bug in "diff -B -M" output.

 Will cook in 'next'.


* jc/checkout-local-track-report (2014-10-14) 1 commit
  (merged to 'next' on 2014-12-15 at e91a7df)
 + checkout: report upstream correctly even with loosely defined branch.*.merge

 The report from "git checkout" on a branch that builds on another
 local branch by setting its branch.*.merge to branch name (not a
 full refname) incorrectly said that the upstream is gone.

 Will cook in 'next'.


* jc/clone-borrow (2014-10-15) 1 commit
  (merged to 'next' on 2014-12-15 at 08fdf77)
 + clone: --dissociate option to mark that reference is only temporary

 Allow "git clone --reference" to be used more safely.

 Will cook in 'next'.

--------------------------------------------------
[Discarded]

* mb/enable-lib-terminal-test-on-newer-darwin (2014-11-14) 1 commit
 . t/lib-terminal: allow TTY tests to run under recent Mac OS

 We probably should drop this ($gmane/259609).


* zk/grep-color-words (2014-10-27) 2 commits
 . Revert "grep: fix match highlighting for combined patterns with context lines"
 . grep: fix match highlighting for combined patterns with context lines

 rs/grep-color-words topic solves it in a different way.

 Will discard.


* jn/dedup-doc-header (2014-12-10) 2 commits
 . put string-list API documentation in one place
 . put strbuf API documentation in one place

 We would want to have an easy way for developers to learn about
 APIs, and also a way to encourage them to keep the API
 documentation up to date when they make changes.  Having header
 comments and API documentation duplicated in two different places
 risked them going out of sync.

 The approach taken by jk/strbuf-doc-to-header is the other way
 around, which people seem to prefer, so this is discarded.


* jt/timer-settime (2014-08-29) 6 commits
 . use timer_settime() for new platforms
 . autoconf: check for timer_settime()
 . autoconf: check for struct itimerspec
 . autoconf: check for struct sigevent
 . autoconf: check for struct timespec
 . autoconf: check for timer_t

 Was wanting for a reroll.


* rs/ref-transaction-reflog (2014-11-03) 15 commits
 . refs.c: allow deleting refs with a broken sha1
 . refs.c: remove lock_any_ref_for_update
 . refs.c: make unlock_ref/close_ref/commit_ref static
 . refs.c: rename log_ref_setup to create_reflog
 . reflog.c: use a reflog transaction when writing during expire
 . refs.c: allow multiple reflog updates during a single transaction
 . refs.c: only write reflog update if msg is non-NULL
 . refs.c: add a flag to allow reflog updates to truncate the log
 . refs.c: add a transaction function to append a reflog entry
 . copy.c: make copy_fd preserve meaningful errno
 . refs.c: add a function to append a reflog entry to a fd
 . refs.c: add a new update_type field to ref_update
 . refs.c: rename the transaction functions
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c make ref_transaction_create a wrapper to ref_transaction_update
 (this branch is used by rs/ref-transaction-rename and rs/ref-transaction-send-pack.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-rename (2014-11-07) 16 commits
 . refs.c: add an err argument to pack_refs
 . refs.c: make lock_packed_refs take an err argument
 . refs.c: make add_packed_ref return an error instead of calling die
 . refs.c: replace the onerr argument in update_ref with a strbuf err
 . refs.c: make the *_packed_refs functions static
 . refs.c: make repack_without_refs static
 . remote.c: use a transaction for deleting refs
 . refs.c: write updates to packed refs when a transaction has more than one ref
 . refs.c: move reflog updates into its own function
 . refs.c: rollback the lockfile before we die() in repack_without_refs
 . refs.c: update rename_ref to use a transaction
 . refs.c: add transaction support for renaming a reflog
 . refs.c: use a stringlist for repack_without_refs
 . refs.c: use packed refs when deleting refs during a transaction
 . refs.c: return error instead of dying when locking fails during transaction
 . refs.c: allow passing raw git_committer_info as email to _update_reflog
 (this branch is used by rs/ref-transaction-send-pack; uses rs/ref-transaction-reflog.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-send-pack (2014-11-07) 7 commits
 . refs.c: add an err argument to create_symref
 . refs.c: add an err argument to create_reflog
 . t5543-atomic-push.sh: add basic tests for atomic pushes
 . push.c: add an --atomic-push argument
 . receive-pack.c: use a single transaction when atomic-push is negotiated
 . send-pack.c: add an --atomic-push command line argument
 . receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses rs/ref-transaction-reflog and rs/ref-transaction-rename.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* sb/simplify-repack-without-refs (2014-11-20) 1 commit
 . refs.c: use a string_list for repack_without_refs


* sb/log-ref-write-fd (2014-11-20) 1 commit
 . refs.c: add a function to append a reflog entry to a fd

 Will be rerolled as a part of a larger series.


* sb/ref-transaction-unify-to-update (2014-11-20) 2 commits
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c: make ref_transaction_create a wrapper for ref_transaction_update
 (this branch is used by sb/ref-transaction-reflog.)

 Code simplification.

 Will be rerolled as a part of a larger series.

^ permalink raw reply	[relevance 2%]

* What's cooking in git.git (Dec 2014, #04; Mon, 22)
@ 2014-12-22 23:17  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-12-22 23:17 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

Quite a few topics have been merged to 'master' as the third batch
for this cycle, on top of the recent "case sensitive .Git" fix that
has been publicized very widely.  The next release which is expected
to be a small one is taking shape.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[Graduated to "master"]

* cc/interpret-trailers-more (2014-11-10) 4 commits
  (merged to 'next' on 2014-12-15 at 77f6c6a)
 + trailer: add test with an old style conflict block
 + trailer: reuse ignore_non_trailer() to ignore conflict lines
 + commit: make ignore_non_trailer() non static
 + Merge branch 'jc/conflict-hint' into cc/interpret-trailers-more
 (this branch uses jc/conflict-hint.)

 "git interpret-trailers" learned to properly handle the
 "Conflicts:" block at the end.


* ch/new-gpg-drops-rfc-1991 (2014-12-12) 4 commits
  (merged to 'next' on 2014-12-15 at 32d7d50)
 + tests: squelch noise from GPG machinery set-up
 + tests: replace binary GPG keyrings with ASCII-armored keys
 + tests: skip RFC1991 tests for gnupg 2.1
 + tests: create gpg homedir on the fly

 Recent GPG changes the keyring format and drops support for RFC1991
 formatted signatures, breaking our existing tests.


* dm/compat-s-ifmt-for-zos (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-15 at 0eb2fe6)
 + compat: convert modes to use portable file type values

 Long overdue departure from the assumption that S_IFMT is shared by
 everybody made in 2005.


* dw/shell-basename-dashdash-before-stripping-leading-dash-from-login (2014-11-25) 1 commit
  (merged to 'next' on 2014-12-15 at 42937b7)
 + git-sh-setup.sh: use dashdash with basename call


* jc/conflict-hint (2014-10-28) 4 commits
  (merged to 'next' on 2014-12-15 at b72475f)
 + merge & sequencer: turn "Conflicts:" hint into a comment
 + builtin/commit.c: extract ignore_non_trailer() helper function
 + merge & sequencer: unify codepaths that write "Conflicts:" hint
 + builtin/merge.c: drop a parameter that is never used
 (this branch is used by cc/interpret-trailers-more.)

 Unlike all the other hints given in the commit log editor, the list
 of conflicted paths were appended at the end without commented out.


* jc/exec-cmd-system-path-leak-fix (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-15 at f926ee5)
 + system_path(): always return free'able memory to the caller

 The function sometimes returned a non-freeable memory and some
 other times returned a piece of memory that must be freed.


* jc/hook-cleanup (2014-12-01) 1 commit
  (merged to 'next' on 2014-12-15 at f5759d0)
 + run-command.c: retire unused run_hook_with_custom_index()

 Remove unused code.


* jc/refer-to-t-readme-from-submitting-patches (2014-11-24) 2 commits
  (merged to 'next' on 2014-12-15 at 0e88699)
 + t/README: justify why "! grep foo" is sufficient
 + SubmittingPatches: refer to t/README for tests


* jg/prompt-localize-temporary (2014-12-12) 1 commit
  (merged to 'next' on 2014-12-15 at bb9cac9)
 + git-prompt.sh: make $f local to __git_eread()

 "git-prompt" (in contrib/) used a variable from the global scope,
 possibly contaminating end-user's namespace.


* jk/always-allow-large-packets (2014-12-10) 1 commit
  (merged to 'next' on 2014-12-15 at c3fb2c8)
 + pkt-line: allow writing of LARGE_PACKET_MAX buffers

 "git push" and "git fetch" did not communicate an overlong refname
 correctly.


* jk/colors (2014-12-09) 6 commits
  (merged to 'next' on 2014-12-15 at 20b045f)
 + parse_color: drop COLOR_BACKGROUND macro
 + diff-highlight: allow configurable colors
 + parse_color: recognize "no$foo" to clear the $foo attribute
 + parse_color: support 24-bit RGB values
 + parse_color: refactor color storage
 + Merge branch 'jn/parse-config-slot' into jk/colors

 "diff-highlight" filter (in contrib/) allows its color output
 to be customized via configuration variables.


* jk/commit-date-approxidate (2014-12-11) 2 commits
  (merged to 'next' on 2014-12-15 at 047530e)
 + commit: always populate GIT_AUTHOR_* variables
 + commit: loosen ident checks when generating template

 Recent update to "git commit" broke amending an existing commit
 with bogus author/committer lines without a valid e-mail address.


* jk/credential-quit (2014-12-04) 2 commits
  (merged to 'next' on 2014-12-15 at 4cfd999)
 + prompt: respect GIT_TERMINAL_PROMPT to disable terminal prompts
 + credential: let helpers tell us to quit

 Credential helpers are asked in turn until one of them give
 positive response, which is cumbersome to turn off when you need to
 run Git in an automated setting.  The credential helper interface
 learned to allow a helper to say "stop, don't ask other helpers."
 Also GIT_TERMINAL_PROMPT environment can be set to false to disable
 our built-in prompt mechanism for passwords.


* jk/for-each-reflog-ent-reverse (2014-12-05) 2 commits
  (merged to 'next' on 2014-12-15 at de71f08)
 + for_each_reflog_ent_reverse: turn leftover check into assertion
 + for_each_reflog_ent_reverse: fix newlines on block boundaries

 The code that reads the reflog from the newer to the older entries
 did not handle an entry that crosses a boundary of block it uses to
 read them correctly.


* jk/lock-ref-sha1-basic-return-errors (2014-11-20) 1 commit
  (merged to 'next' on 2014-12-15 at c48b110)
 + lock_ref_sha1_basic: do not die on locking errors

 Correct an API anomaly.


* jk/read-packed-refs-without-path-max (2014-12-10) 3 commits
  (merged to 'next' on 2014-12-15 at c6d6f56)
 + read_packed_refs: use skip_prefix instead of static array
 + read_packed_refs: pass strbuf to parse_ref_line
 + read_packed_refs: use a strbuf for reading lines

 Git did not correctly read an overlong refname from a packed refs
 file.


* jk/test-asan (2014-12-11) 1 commit
  (merged to 'next' on 2014-12-15 at d24cb92)
 + t: support clang/gcc AddressSanitizer


* js/fsck-tag-validation (2014-12-09) 2 commits
  (merged to 'next' on 2014-12-15 at 455f26c)
 + index-pack: terminate object buffers with NUL
 + fsck: properly bound "invalid tag name" error message

 New tag object format validation added in 2.2 showed garbage
 after a tagname it reported in its error message.


* js/push-to-deploy (2014-11-30) 2 commits
  (merged to 'next' on 2014-12-15 at ef8c99f)
 + t5516: more tests for receive.denyCurrentBranch=updateInstead
 + receive-pack: add another option for receive.denyCurrentBranch
 (this branch is used by jc/push-to-checkout.)

 "git push" into a repository with a working tree normally refuses
 to modify the branch that is checked out.  The command learned to
 optionally do an equivalent of "git reset --hard" only when there
 is no change to the working tree and the index instead, which would
 be useful to "deploy" by pushing into a repository.


* js/t5000-dont-copy-bin-sh (2014-11-24) 1 commit
  (merged to 'next' on 2014-12-15 at 65ffd05)
 + t5000 on Windows: do not mistake "sh.exe" as "sh"


* js/test-hashmap-squelch-gcc (2014-12-09) 1 commit
  (merged to 'next' on 2014-12-15 at a8da691)
 + test-hashmap: squelch gcc compiler warning


* mg/add-ignore-errors (2014-11-21) 1 commit
  (merged to 'next' on 2014-12-15 at 3834789)
 + add: ignore only ignored files

 "git add --ignore-errors ..." did not ignore an error to
 give a file that did not exist.


* mg/branch-d-m-f (2014-12-09) 2 commits
  (merged to 'next' on 2014-12-15 at 8366f2c)
 + branch: allow -f with -m and -d
 + t3200-branch: test -M

 "git branch -d" (delete) and "git branch -m" (move) learned to
 honor "-f" (force) flag; unlike many other subcommands, the way to
 force these have been with separate "-D/-M" options, which was
 inconsistent.


* mg/doc-check-ignore-tracked-are-not-ignored (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-15 at c50f748)
 + check-ignore: clarify treatment of tracked files


* mh/find-uniq-abbrev (2014-11-26) 1 commit
  (merged to 'next' on 2014-12-15 at e3b2b62)
 + sha1_name: avoid unnecessary sha1 lookup in find_unique_abbrev

 The code to abbreviate an object name to its short unique prefix
 has been optimized when no abbreviation was requested.


* mh/simplify-repack-without-refs (2014-11-25) 7 commits
  (merged to 'next' on 2014-12-15 at 351e03e)
 + sort_string_list(): rename to string_list_sort()
 + prune_remote(): iterate using for_each_string_list_item()
 + prune_remote(): rename local variable
 + repack_without_refs(): make the refnames argument a string_list
 + prune_remote(): sort delete_refs_list references en masse
 + prune_remote(): initialize both delete_refs lists in a single loop
 + prune_remote(): exit early if there are no stale references

 "git remote update --prune" to drop many refs has been optimized.


* nd/ls-tree-pathspec (2014-12-01) 5 commits
  (merged to 'next' on 2014-12-15 at 8da6e09)
 + t3102: style modernization
 + t3102: document that ls-tree does not yet support negated pathspec
 + ls-tree: disable negative pathspec because it's not supported
 + ls-tree: remove path filtering logic in show_tree
 + tree.c: update read_tree_recursive callback to pass strbuf as base

 "git ls-tree" does not support path selection based on negative
 pathspecs, but did not error out when negative pathspecs are given.


* nd/split-index (2014-12-11) 1 commit
  (merged to 'next' on 2014-12-15 at ed6490c)
 + index-format.txt: add a missing closing quote

 A typofix to the documentation of a feature already in the release.


* ok/rebase-i-count-todo (2014-12-10) 1 commit
  (merged to 'next' on 2014-12-15 at 4a1f7ed)
 + Show number of TODO items for interactive rebase


* pb/am-message-id-footer (2014-11-25) 2 commits
  (merged to 'next' on 2014-12-15 at b44b6bd)
 + git-am: add --message-id/--no-message-id
 + git-mailinfo: add --message-id

 "git am" learned "--message-id" option to copy the message ID of
 the incoming e-mail to the log message of resulting commit.


* pb/send-email-te (2014-11-25) 2 commits
  (merged to 'next' on 2014-12-15 at 38c2810)
 + git-send-email: add --transfer-encoding option
 + git-send-email: delay creation of MIME headers
 (this branch is used by jc/t9001-modernise.)

 "git send-email" learned "--transfer-encoding" option to force
 a non-fault Content-Transfer-Encoding header (e.g. base64).


* po/doc-assume-unchanged (2014-12-09) 2 commits
  (merged to 'next' on 2014-12-15 at 646e77e)
 + gitignore.txt: do not suggest assume-unchanged
 + doc: make clear --assume-unchanged's user contract

 Fixes long-standing misunderstanding of what assume-unchanged is
 about.  Some text near what is removed by the bottom patch may also
 have to be removed.


* ps/new-workdir-into-empty-directory (2014-12-03) 1 commit
  (merged to 'next' on 2014-12-15 at 0787b56)
 + git-new-workdir: don't fail if the target directory is empty

 "git new-workdir" (in contrib/) can be used to populate an empty
 and existing directory now.


* rj/no-xopen-source-for-cygwin (2014-11-24) 1 commit
  (merged to 'next' on 2014-12-15 at 6e8e9ff)
 + git-compat-util.h: don't define _XOPEN_SOURCE on cygwin

 Avoid compilation warnings on recent gcc toolchain on Cygwin.


* rj/t0050-passes (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-15 at f56c339)
 + t0050-*.sh: mark the rename (case change) test as passing


* rs/use-strbuf-complete-line (2014-12-12) 1 commit
  (merged to 'next' on 2014-12-15 at d6426a0)
 + use strbuf_complete_line() for adding a newline if needed


* rt/completion-tag (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-15 at b03ee39)
 + completion: add git-tag options


* rt/for-each-ref-spell-tcl-as-Tcl (2014-11-30) 1 commit
  (merged to 'next' on 2014-12-15 at c0fcefb)
 + for-each-ref: correct spelling of Tcl in option description


* rw/apply-does-not-take-ignore-date (2014-12-09) 1 commit
  (merged to 'next' on 2014-12-15 at ded2f99)
 + git-am.txt: --ignore-date flag is not passed to git-apply


* sb/string-list (2014-12-04) 3 commits
  (merged to 'next' on 2014-12-15 at 8bb8ddd)
 + string_list: remove string_list_insert_at_index() from its API
 + mailmap: use higher level string list functions
 + string_list: document string_list_(insert,lookup)

 API simplification.


* sv/doc-stripspace (2014-12-04) 1 commit
  (merged to 'next' on 2014-12-15 at e86f8ba)
 + Documentation/git-stripspace: add synopsis for --comment-lines


* tb/config-core-filemode-check-on-broken-fs (2014-11-21) 1 commit
  (merged to 'next' on 2014-12-15 at 3e5490b)
 + init-db: improve the filemode trustability check

 Some filesystems assign filemodes in a strange way, fooling then
 automatic "filemode trustability" check done during a new
 repository creation.


* tb/t0027-eol-conversion (2014-12-05) 1 commit
  (merged to 'next' on 2014-12-15 at ba24e75)
 + t0027: check the eol conversion warnings

--------------------------------------------------
[New Topics]

* bb/update-unicode-table (2014-12-22) 5 commits
 - update_unicode.sh: delete the command group
 - update_unicode.sh: make the output structure visible
 - update_unicode.sh: shorten uniset invocation path
 - update_unicode.sh: set UNICODE_DIR only once
 - update_unicode.sh: simplify output capture

 Simplify the procedure to generate unicode table.

 Will merge to 'next'.


* bc/fetch-thin-less-aggressive-in-normal-repository (2014-12-22) 3 commits
 - pack-objects: use --objects-edge-aggressive only for shallow repos
 - rev-list: add an option to mark fewer edges as uninteresting
 - Documentation: add missing article in rev-list-options.txt

 Earlier we made "rev-list --object-edge" more aggressively list the
 objects at the edge commits, in order to reduce number of objects
 fetched into a shallow repository, but the change affected cases
 other than "fetching into a shallow repository" and made it
 unusably slow (e.g. fetching into a normal repository should not
 have to suffer the overhead from extra processing).  Limit it to a
 more specific case by introducing --objects-edge-aggressive, a new
 option to rev-list.

 Seems to break t5500 when merged to 'pu'.


* es/squelch-openssl-warnings-on-macosx (2014-12-18) 1 commit
 - git-compat-util: suppress unavoidable Apple-specific deprecation warnings

 Squelch useless compiler warnings on Mac OS X.

 Will merge to 'next'.


* jh/pre-push-sample-no-custom-ifs (2014-12-22) 1 commit
 - pre-push.sample: remove unnecessary and misleading IFS=' '

 The sample pre-push hook used customized IFS=' ' for no good reason.

 Will merge to 'next'.


* mh/update-ref-verify (2014-12-11) 2 commits
 - update-ref: fix "verify" command with missing <oldvalue>
 - t1400: add some more tests of "update-ref --stdin"'s verify command

 "git update-ref --stdin"'s verify command did not work well when
 <oldvalue>, which is documented as optional, was missing.

 Will merge to 'next'.


* sb/atomic-push (2014-12-22) 7 commits
 - t5543-atomic-push.sh: add basic tests for atomic pushes
 - push.c: add an --atomic argument
 - receive-pack: move execute_commands_non_atomic before execute_commands
 - receive-pack.c: receive-pack.c: use a single ref_transaction for atomic pushes
 - send-pack.c: add --atomic command line argument
 - send-pack: rename ref_update_to_be_sent to check_to_send_update
 - receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses mh/reflog-expire.)

 "git push" has been taught a "--atomic" option that makes push to
 update more than one ref an "all-or-none" affair.

 Will merge to 'next'.


* sb/dco-indentation-fix (2014-12-22) 1 commit
 - Documentation/SubmittingPatches: unify whitespace/tabs for the DCO

 Will merge to 'next'.


* sb/t5400-remove-unused (2014-12-16) 1 commit
 - t5400: remove dead code

 Will merge to 'next'.


* tf/prompt-preserve-exit-status (2014-12-22) 1 commit
 - git-prompt: preserve value of $? inside shell prompt

 Using the exit status of the last command in the prompt, e.g.
 PS1='$(__git_ps1) $? ', did not work well because the helper
 function stomped on the exit status.

 Will merge to 'next'.

--------------------------------------------------
[Stalled]

* pw/remote-set-url-fetch (2014-11-26) 1 commit
 - remote: add --fetch and --both options to set-url

 Expecting a reroll.


* ms/submodule-update-config-doc (2014-11-03) 1 commit
 - submodule: clarify documentation for update subcommand

 Needs a reroll ($gmane/259037).


* je/quiltimport-no-fuzz (2014-10-21) 2 commits
 - git-quiltimport: flip the default not to allow fuzz
 - git-quiltimport.sh: allow declining fuzz with --exact option

 "quiltimport" drove "git apply" always with -C1 option to reduce
 context of the patch in order to give more chance to somewhat stale
 patches to apply.  Add an "--exact" option to disable, and also
 "-C$n" option to customize this behaviour.  The top patch
 optionally flips the default to "--exact".

 Tired of waiting for an Ack; will discard.


* jc/push-cert-hmac-optim (2014-09-25) 2 commits
 - receive-pack: truncate hmac early and convert only necessary bytes
 - sha1_to_hex: split out "hex-format n bytes" helper and use it

 This is "we could do this if we wanted to", not "we measured and it
 improves performance critical codepath".

 Will perhaps drop.


* mt/patch-id-stable (2014-06-10) 1 commit
 - patch-id: change default to stable

 Teaches "git patch-id" to compute the patch ID that does not change
 when the files in a single patch is reordered. As this new algorithm
 is backward incompatible, the last bit to flip it to be the default
 is left out of 'master' for now.

 Nobody seems to be jumping up & down requesting this last step,
 which makes the result somewhat backward incompatible.
 Will perhaps drop.


* tr/remerge-diff (2014-11-10) 9 commits
 - t4213: avoid "|" in sed regexp
 - log --remerge-diff: show what the conflict resolution changed
 - name-hash: allow dir hashing even when !ignore_case
 - merge-recursive: allow storing conflict hunks in index
 - merge_diff_mode: fold all merge diff variants into an enum
 - combine-diff: do not pass revs->dense_combined_merges redundantly
 - merge-recursive: -Xindex-only to leave worktree unchanged
 - merge-recursive: internal flag to avoid touching the worktree
 - merge-recursive: remove dead conditional in update_stages()

 "log -p" output learns a new way to let users inspect a merge
 commit by showing the differences between the automerged result
 with conflicts the person who recorded the merge would have seen
 and the final conflict resolution that was recorded in the merge.

 Waiting for a reroll ($gmane/256591).


* hv/submodule-config (2014-11-11) 4 commits
 - do not die on error of parsing fetchrecursesubmodules option
 - use new config API for worktree configurations of submodules
 - extract functions for submodule config set and lookup
 - implement submodule config cache for lookup of submodule names

 Kicked back to 'pu' per request ($gmane/255610).


* ab/add-interactive-show-diff-func-name (2014-05-12) 2 commits
 - SQUASH??? git-add--interactive: Preserve diff heading when splitting hunks
 - git-add--interactive: Preserve diff heading when splitting hunks

 Waiting for a reroll.


* jn/gitweb-utf8-in-links (2014-05-27) 1 commit
 - gitweb: Harden UTF-8 handling in generated links

 $gmane/250758?


* ss/userdiff-update-csharp-java (2014-06-02) 2 commits
 - userdiff: support Java try keyword
 - userdiff: support C# async methods and correct C# keywords

 Reviews sent; waiting for a response.


* bg/rebase-off-of-previous-branch (2014-04-16) 1 commit
 - git-rebase: print name of rev when using shorthand

 Teach "git rebase -" to report the concrete name of the branch
 (i.e. the previous one).

 But it stops short and does not do the same for "git rebase @{-1}".
 Expecting a reroll.


* rb/merge-prepare-commit-msg-hook (2014-01-10) 4 commits
 - merge: drop unused arg from abort_commit method signature
 - merge: make prepare_to_commit responsible for write_merge_state
 - t7505: ensure cleanup after hook blocks merge
 - t7505: add missing &&

 Expose more merge states (e.g. $GIT_DIR/MERGE_MODE) to hooks that
 run during "git merge".  The log message stresses too much on one
 hook, prepare-commit-msg, but it would equally apply to other hooks
 like post-merge, I think.

 Waiting for a reroll.


* jc/graph-post-root-gap (2013-12-30) 3 commits
 - WIP: document what we want at the end
 - graph: remove unused code a bit
 - graph: stuff the current commit into graph->columns[]

 This was primarily a RFH ($gmane/239580).


* tg/perf-lib-test-perf-cleanup (2013-09-19) 2 commits
 - perf-lib: add test_perf_cleanup target
 - perf-lib: split starting the test from the execution

 Add test_perf_cleanup shell function to the perf suite, that allows
 the script writers to define a test with a clean-up action.

 Will hold.


* jc/show-branch (2014-03-24) 5 commits
 - show-branch: use commit slab to represent bitflags of arbitrary width
 - show-branch.c: remove "all_mask"
 - show-branch.c: abstract out "flags" operation
 - show-branch.c: lift all_mask/all_revs to a global static
 - show-branch.c: update comment style

 Waiting for the final step to lift the hard-limit before sending it out.

--------------------------------------------------
[Cooking]

* ye/http-accept-language (2014-12-22) 1 commit
 - http: Add Accept-Language header if possible

 An earlier iteration broke various people ($gmane/260903).  Please
 retest and comment.


* jk/strbuf-doc-to-header (2014-12-12) 4 commits
 - strbuf.h: reorganize api function grouping headers
 - strbuf.h: format asciidoc code blocks as 4-space indent
 - strbuf.h: drop asciidoc list formatting from API docs
 - strbuf: migrate api-strbuf.txt documentation to strbuf.h

 Resolve the "doc vs header" to favor the latter.

 Expecting to be rerolled.


* mh/reflog-expire (2014-12-22) 24 commits
 - refs.c: let fprintf handle the formatting
 - refs.c: don't expose the internal struct ref_lock in the header file
 - lock_any_ref_for_update(): inline function
 - refs.c: remove unlock_ref/close_ref/commit_ref from the refs api
 - reflog_expire(): new function in the reference API
 - expire_reflog(): treat the policy callback data as opaque
 - Move newlog and last_kept_sha1 to "struct expire_reflog_cb"
 - expire_reflog(): move rewrite to flags argument
 - expire_reflog(): move verbose to flags argument
 - expire_reflog(): pass flags through to expire_reflog_ent()
 - struct expire_reflog_cb: a new callback data type
 - Rename expire_reflog_cb to expire_reflog_policy_cb
 - expire_reflog(): move updateref to flags argument
 - expire_reflog(): move dry_run to flags argument
 - expire_reflog(): add a "flags" argument
 - expire_reflog(): extract two policy-related functions
 - Extract function should_expire_reflog_ent()
 - expire_reflog(): use a lock_file for rewriting the reflog file
 - expire_reflog(): return early if the reference has no reflog
 - expire_reflog(): rename "ref" parameter to "refname"
 - expire_reflog(): it's not an each_ref_fn anymore
 - refs.c: add a function to append a reflog entry to a fd
 - refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 - refs.c: make ref_transaction_create a wrapper for ref_transaction_update
 (this branch is used by sb/atomic-push.)

 Restructure "reflog expire" to fit the reflogs better with the
 recently updated ref API.

 Looked reasonable (except that some shortlog entries stood out like
 a sore thumb).


* po/doc-core-ignorestat (2014-12-12) 1 commit
 - doc: core.ignoreStat clarify the --assume-unchanged effect

 Expecting a reroll.


* jk/add-i-read-error (2014-12-15) 1 commit
 - add--interactive: leave main loop on read error

 "git add -i" did not notice when the interactive command input
 stream went away and kept asking.

 Will merge to 'next'.


* pd/completion-filenames-fix (2014-12-15) 1 commit
 - Update documentation occurrences of filename .sh

 The top-of-the-file instruction for completion scripts (in contrib/)
 did not name the files correctly.

 Will merge to 'next'.


* rd/send-email-2047-fix (2014-12-15) 2 commits
 - send-email: handle adjacent RFC 2047-encoded words properly
 - send-email: align RFC 2047 decoding more closely with the spec

 "git send-email" did not handle RFC 2047 encoded headers quite
 right.

 Will merge to 'next'.


* jn/doc-api-errors (2014-12-04) 1 commit
 - doc: document error handling functions and conventions

 For discussion.


* jn/rerere-fail-on-auto-update-failure (2014-12-03) 2 commits
 - SQUASH???
 - rerere: error out on autoupdate failure

 Will be rerolled as a part of a larger series.


* jc/push-to-checkout (2014-12-01) 2 commits
 - receive-pack: support push-to-checkout hook
 - receive-pack: refactor updateInstead codepath

 Extending the js/push-to-deploy topic, the behaviour of "git push"
 when updating the working tree and the index with an update to the
 branch that is checked out can be tweaked by push-to-checkout hook.

 Needs docs.


* lh/send-email-hide-x-mailer (2014-12-15) 2 commits
 - test/send-email: --[no-]xmailer tests
 - send-email: add --[no-]xmailer option

 "git send-email" normally identifies itself via X-Mailer: header
 in the message it sends out.  A new command line flag allows the
 header to be squelched.

 Will merge to 'next'.


* nd/list-files (2014-12-01) 19 commits
 - list-files: -M aka diff-cached
 - list-files -F: show submodules with the new indicator '&'
 - list-files: add -F/--classify
 - list-files: show directories as well as files
 - list-files: do not show duplicate cached entries
 - list-files: sort output and remove duplicates
 - list-files: add -t back
 - list-files: add -1 short for --no-column
 - list-files: add -R/--recursive short for --max-depth=-1
 - list-files: -u does not imply showing stages
 - list-files: a user friendly version of ls-files and more
 - ls-files: support --max-depth
 - ls-files: add --column
 - ls-files: add --color to highlight file names
 - ls-files: buffer full item in strbuf before printing
 - ls_colors.c: highlight submodules like directories
 - ls_colors.c: add a function to color a file name
 - ls_colors.c: parse color.ls.* from config file
 - ls_colors.c: add $LS_COLORS parsing code

 A new "git list-files" Porcelain command, "ls-files" with bells and
 whistles.


* nd/multiple-work-trees (2014-12-01) 34 commits
 - git-common-dir: make "modules/" per-working-directory directory
 - checkout: do not fail if target is an empty directory
 - t2025: add a test to make sure grafts is working from a linked checkout
 - checkout: don't require a work tree when checking out into a new one
 - git_path(): keep "info/sparse-checkout" per work-tree
 - count-objects: report unused files in $GIT_DIR/worktrees/...
 - gc: support prune --worktrees
 - gc: factor out gc.pruneexpire parsing code
 - gc: style change -- no SP before closing parenthesis
 - checkout: clean up half-prepared directories in --to mode
 - checkout: reject if the branch is already checked out elsewhere
 - prune: strategies for linked checkouts
 - checkout: support checking out into a new working directory
 - use new wrapper write_file() for simple file writing
 - wrapper.c: wrapper to open a file, fprintf then close
 - setup.c: support multi-checkout repo setup
 - setup.c: detect $GIT_COMMON_DIR check_repository_format_gently()
 - setup.c: convert check_repository_format_gently to use strbuf
 - setup.c: detect $GIT_COMMON_DIR in is_git_directory()
 - setup.c: convert is_git_directory() to use strbuf
 - git-stash: avoid hardcoding $GIT_DIR/logs/....
 - *.sh: avoid hardcoding $GIT_DIR/hooks/...
 - git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects
 - $GIT_COMMON_DIR: a new environment variable
 - commit: use SEQ_DIR instead of hardcoding "sequencer"
 - fast-import: use git_path() for accessing .git dir instead of get_git_dir()
 - reflog: avoid constructing .lock path with git_path
 - *.sh: respect $GIT_INDEX_FILE
 - git_path(): be aware of file relocation in $GIT_DIR
 - path.c: group git_path(), git_pathdup() and strbuf_git_path() together
 - path.c: rename vsnpath() to do_git_path()
 - git_snpath(): retire and replace with strbuf_git_path()
 - path.c: make get_pathname() call sites return const char *
 - path.c: make get_pathname() return strbuf instead of static buffer

 A replacement for contrib/workdir/git-new-workdir that does not
 rely on symbolic links and make sharing of objects and refs safer
 by making the borrowee and borrowers aware of each other.


* sb/copy-fd-errno (2014-11-17) 1 commit
 - copy.c: make copy_fd preserve meaningful errno

 Will be rerolled as a part of a larger series.


* jc/t9001-modernise (2014-11-25) 5 commits
 - t9001: style modernisation phase #5
 - t9001: style modernisation phase #4
 - t9001: style modernisation phase #3
 - t9001: style modernisation phase #2
 - t9001: style modernisation phase #1


* jk/approxidate-avoid-y-d-m-over-future-dates (2014-11-13) 2 commits
  (merged to 'next' on 2014-12-15 at 397e986)
 + approxidate: allow ISO-like dates far in the future
 + pass TIME_DATE_NOW to approxidate future-check

 Traditionally we tried to avoid interpreting date strings given by
 the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
 used early November 2014 was taken as "October 12, 2014" because it
 is likely that a date in the future, December 10, is a mistake.

 Loosen this and do not tiebreak by future-ness of the date when

 (1) ISO-like format is used, and
 (2) the string can make sense interpreted as both y-m-d and y-d-m.

 Will cook in 'next'.


* br/imap-send-verbosity (2014-11-05) 1 commit
  (merged to 'next' on 2014-12-15 at 504af0b)
 + imap-send: use parse options API to determine verbosity
 (this branch is used by br/imap-send-via-libcurl.)

 Will cook in 'next'.


* br/imap-send-via-libcurl (2014-11-10) 1 commit
  (merged to 'next' on 2014-12-15 at 90db637)
 + git-imap-send: use libcurl for implementation
 (this branch uses br/imap-send-verbosity.)

 Newer libCurl knows how to talk IMAP; "git imap-send" has been
 updated to use this instead of a hand-rolled OpenSSL calls.

 Will cook in 'next'.


* nd/lockfile-absolute (2014-11-03) 1 commit
  (merged to 'next' on 2014-12-15 at 34db9af)
 + lockfile.c: store absolute path

 The lockfile API can get confused which file to clean up when the
 process moved the $cwd after creating a lockfile.

 Will cook in 'next'.


* jc/merge-bases (2014-10-30) 2 commits
  (merged to 'next' on 2014-12-15 at cac279e)
 + get_merge_bases(): always clean-up object flags
 + bisect: clean flags after checking merge bases

 The get_merge_bases*() API was easy to misuse by careless
 copy&paste coders, leaving object flags tainted in the commits that
 needed to be traversed.

 Will cook in 'next'.


* jc/strbuf-add-lines-avoid-sp-ht-sequence (2014-10-27) 1 commit
  (merged to 'next' on 2014-12-15 at b499889)
 + strbuf_add_commented_lines(): avoid SP-HT sequence in commented lines

 The commented output used to blindly add a SP before the payload
 line, resulting in "# \t<indented text>\n" when the payload began
 with a HT.  Instead, produce "#\t<indented text>\n".

 Will cook in 'next'.


* nd/untracked-cache (2014-12-15) 24 commits
 - SQUASH???
 - untracked cache: guard and disable on system changes
 - mingw32: add uname()
 - t7063: tests for untracked cache
 - update-index: test the system before enabling untracked cache
 - update-index: manually enable or disable untracked cache
 - status: enable untracked cache
 - untracked-cache: temporarily disable with $GIT_DISABLE_UNTRACKED_CACHE
 - untracked cache: mark index dirty if untracked cache is updated
 - untracked cache: print stats with $GIT_TRACE_UNTRACKED_STATS
 - untracked cache: avoid racy timestamps
 - read-cache.c: split racy stat test to a separate function
 - untracked cache: invalidate at index addition or removal
 - untracked cache: load from UNTR index extension
 - untracked cache: save to an index extension
 - ewah: add convenient wrapper ewah_serialize_strbuf()
 - untracked cache: don't open non-existent .gitignore
 - untracked cache: mark what dirs should be recursed/saved
 - untracked cache: record/validate dir mtime and reuse cached output
 - untracked cache: make a wrapper around {open,read,close}dir()
 - untracked cache: invalidate dirs recursively if .gitignore changes
 - untracked cache: initial untracked cache validation
 - untracked cache: record .gitignore information and dir hierarchy
 - dir.c: optionally compute sha-1 of a .gitignore file

 Comments?


* jc/diff-b-m (2014-10-23) 1 commit
  (merged to 'next' on 2014-12-15 at 59c6636)
 + diff -B -M: fix output for "copy and then rewrite" case

 Fix long-standing bug in "diff -B -M" output.

 Will cook in 'next'.


* jc/checkout-local-track-report (2014-10-14) 1 commit
  (merged to 'next' on 2014-12-15 at e91a7df)
 + checkout: report upstream correctly even with loosely defined branch.*.merge

 The report from "git checkout" on a branch that builds on another
 local branch by setting its branch.*.merge to branch name (not a
 full refname) incorrectly said that the upstream is gone.

 Will cook in 'next'.


* jc/clone-borrow (2014-10-15) 1 commit
  (merged to 'next' on 2014-12-15 at 08fdf77)
 + clone: --dissociate option to mark that reference is only temporary

 Allow "git clone --reference" to be used more safely.

 Will cook in 'next'.

--------------------------------------------------
[Discarded]

* mb/enable-lib-terminal-test-on-newer-darwin (2014-11-14) 1 commit
 . t/lib-terminal: allow TTY tests to run under recent Mac OS

 We probably should drop this ($gmane/259609).


* zk/grep-color-words (2014-10-27) 2 commits
 . Revert "grep: fix match highlighting for combined patterns with context lines"
 . grep: fix match highlighting for combined patterns with context lines

 rs/grep-color-words topic solves it in a different way.

 Will discard.


* jn/dedup-doc-header (2014-12-10) 2 commits
 . put string-list API documentation in one place
 . put strbuf API documentation in one place

 We would want to have an easy way for developers to learn about
 APIs, and also a way to encourage them to keep the API
 documentation up to date when they make changes.  Having header
 comments and API documentation duplicated in two different places
 risked them going out of sync.

 The approach taken by jk/strbuf-doc-to-header is the other way
 around, which people seem to prefer, so this is discarded.


* jt/timer-settime (2014-08-29) 6 commits
 . use timer_settime() for new platforms
 . autoconf: check for timer_settime()
 . autoconf: check for struct itimerspec
 . autoconf: check for struct sigevent
 . autoconf: check for struct timespec
 . autoconf: check for timer_t

 Was wanting for a reroll.


* rs/ref-transaction-reflog (2014-11-03) 15 commits
 . refs.c: allow deleting refs with a broken sha1
 . refs.c: remove lock_any_ref_for_update
 . refs.c: make unlock_ref/close_ref/commit_ref static
 . refs.c: rename log_ref_setup to create_reflog
 . reflog.c: use a reflog transaction when writing during expire
 . refs.c: allow multiple reflog updates during a single transaction
 . refs.c: only write reflog update if msg is non-NULL
 . refs.c: add a flag to allow reflog updates to truncate the log
 . refs.c: add a transaction function to append a reflog entry
 . copy.c: make copy_fd preserve meaningful errno
 . refs.c: add a function to append a reflog entry to a fd
 . refs.c: add a new update_type field to ref_update
 . refs.c: rename the transaction functions
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c make ref_transaction_create a wrapper to ref_transaction_update
 (this branch is used by rs/ref-transaction-rename and rs/ref-transaction-send-pack.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-rename (2014-11-07) 16 commits
 . refs.c: add an err argument to pack_refs
 . refs.c: make lock_packed_refs take an err argument
 . refs.c: make add_packed_ref return an error instead of calling die
 . refs.c: replace the onerr argument in update_ref with a strbuf err
 . refs.c: make the *_packed_refs functions static
 . refs.c: make repack_without_refs static
 . remote.c: use a transaction for deleting refs
 . refs.c: write updates to packed refs when a transaction has more than one ref
 . refs.c: move reflog updates into its own function
 . refs.c: rollback the lockfile before we die() in repack_without_refs
 . refs.c: update rename_ref to use a transaction
 . refs.c: add transaction support for renaming a reflog
 . refs.c: use a stringlist for repack_without_refs
 . refs.c: use packed refs when deleting refs during a transaction
 . refs.c: return error instead of dying when locking fails during transaction
 . refs.c: allow passing raw git_committer_info as email to _update_reflog
 (this branch is used by rs/ref-transaction-send-pack; uses rs/ref-transaction-reflog.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-send-pack (2014-11-07) 7 commits
 . refs.c: add an err argument to create_symref
 . refs.c: add an err argument to create_reflog
 . t5543-atomic-push.sh: add basic tests for atomic pushes
 . push.c: add an --atomic-push argument
 . receive-pack.c: use a single transaction when atomic-push is negotiated
 . send-pack.c: add an --atomic-push command line argument
 . receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses rs/ref-transaction-reflog and rs/ref-transaction-rename.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* sb/simplify-repack-without-refs (2014-11-20) 1 commit
 . refs.c: use a string_list for repack_without_refs


* sb/log-ref-write-fd (2014-11-20) 1 commit
 . refs.c: add a function to append a reflog entry to a fd

 Will be rerolled as a part of a larger series.


* sb/ref-transaction-unify-to-update (2014-11-20) 2 commits
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c: make ref_transaction_create a wrapper for ref_transaction_update
 (this branch is used by sb/ref-transaction-reflog.)

 Code simplification.

 Will be rerolled as a part of a larger series.

* sb/write-sha1-update-reflog (2014-11-24) 1 commit
 . refs.c: move reflog updates into its own function

 Moves a part of function around to add a helper that still only has
 one caller.  Need to see how this helps in a bigger picture.


* sb/ref-transaction-reflog (2014-12-03) 2 commits
 . refs.c: rename transaction.updates to transaction.ref_updates
 . refs.c: rename the transaction functions
 (this branch uses sb/ref-transaction-unify-to-update.)

 Will be rerolled as a part of a larger series.

^ permalink raw reply	[relevance 2%]

* What's cooking in git.git (Dec 2014, #05; Mon, 29)
@ 2014-12-29 21:28  3% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2014-12-29 21:28 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

It has been understandably somewhat a slow week, and this will be
the last issue of "What's cooking" report for this year.  See you
all in the new year.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[Graduated to "master"]

* jc/t9001-modernise (2014-11-25) 5 commits
  (merged to 'next' on 2014-12-23 at 3a2ec87)
 + t9001: style modernisation phase #5
 + t9001: style modernisation phase #4
 + t9001: style modernisation phase #3
 + t9001: style modernisation phase #2
 + t9001: style modernisation phase #1


* mh/update-ref-verify (2014-12-11) 2 commits
  (merged to 'next' on 2014-12-23 at 3aa9a62)
 + update-ref: fix "verify" command with missing <oldvalue>
 + t1400: add some more tests of "update-ref --stdin"'s verify command

 "git update-ref --stdin"'s verify command did not work well when
 <oldvalue>, which is documented as optional, was missing.

--------------------------------------------------
[New Topics]

* bw/maint-0090-awk-tweak (2014-12-23) 1 commit
  (merged to 'next' on 2014-12-29 at 9301c36)
 + t0090: tweak awk statement for Solaris /usr/xpg4/bin/awk

 Will merge to 'master'.


* cc/bisect-rev-parsing (2014-12-29) 2 commits
 - bisect: add test to check that revs are properly parsed
 - bisect: parse revs before passing them to check_expected_revs()

 The logic in "git bisect bad HEAD" etc. to avoid forcing the test
 of the common ancestor of bad and good commits was broken.

 Will merge to 'next'.


* es/checkout-index-temp (2014-12-29) 5 commits
 - checkout-index: fix --temp relative path mangling
 - t2004: demonstrate broken relative path printing
 - t2004: standardize file naming in symlink test
 - t2004: drop unnecessary write-tree/read-tree
 - t2004: modernize style

 "git checkout-index --temp=$target $path" did not work correctly
 for paths outside the current subdirectory in the project.

 Will merge to 'next'.


* js/remote-add-with-insteadof (2014-12-23) 2 commits
 - Add a regression test for 'git remote add <existing> <same-url>'
 - git remote: allow adding remotes agreeing with url.<...>.insteadOf

 "git remote add $name $URL" is now allowed when "url.$URL.insteadOf"
 is already defined.


* rs/plug-strbuf-leak-in-lock-ref (2014-12-29) 1 commit
 - refs: plug strbuf leak in lock_ref_sha1_basic()

 Will merge to 'next'.


* rs/plug-strbuf-leak-in-merge (2014-12-29) 1 commit
 - merge: release strbuf after use in suggest_conflicts()

 Will merge to 'next'.


* rs/simplify-parsing-commit-tree-S (2014-12-29) 1 commit
 - commit-tree: simplify parsing of option -S using skip_prefix()

 Will merge to 'next'.


* rs/simplify-transport-get (2014-12-29) 1 commit
 - transport: simplify duplicating a substring in transport_get() using xmemdupz()

 Will merge to 'next'.


* sb/doc-submitting-patches-keep-notes (2014-12-29) 1 commit
 - Documentation/SubmittingPatches: Explain the rationale of git notes

 Will merge to 'next'.

--------------------------------------------------
[Stalled]

* pw/remote-set-url-fetch (2014-11-26) 1 commit
 - remote: add --fetch and --both options to set-url

 Expecting a reroll.


* ms/submodule-update-config-doc (2014-11-03) 1 commit
 - submodule: clarify documentation for update subcommand

 Needs a reroll ($gmane/259037).


* je/quiltimport-no-fuzz (2014-10-21) 2 commits
 - git-quiltimport: flip the default not to allow fuzz
 - git-quiltimport.sh: allow declining fuzz with --exact option

 "quiltimport" drove "git apply" always with -C1 option to reduce
 context of the patch in order to give more chance to somewhat stale
 patches to apply.  Add an "--exact" option to disable, and also
 "-C$n" option to customize this behaviour.  The top patch
 optionally flips the default to "--exact".

 Tired of waiting for an Ack; will discard.


* jc/push-cert-hmac-optim (2014-09-25) 2 commits
 - receive-pack: truncate hmac early and convert only necessary bytes
 - sha1_to_hex: split out "hex-format n bytes" helper and use it

 This is "we could do this if we wanted to", not "we measured and it
 improves performance critical codepath".

 Will perhaps drop.


* mt/patch-id-stable (2014-06-10) 1 commit
 - patch-id: change default to stable

 Teaches "git patch-id" to compute the patch ID that does not change
 when the files in a single patch is reordered. As this new algorithm
 is backward incompatible, the last bit to flip it to be the default
 is left out of 'master' for now.

 Nobody seems to be jumping up & down requesting this last step,
 which makes the result somewhat backward incompatible.
 Will perhaps drop.


* tr/remerge-diff (2014-11-10) 9 commits
 - t4213: avoid "|" in sed regexp
 - log --remerge-diff: show what the conflict resolution changed
 - name-hash: allow dir hashing even when !ignore_case
 - merge-recursive: allow storing conflict hunks in index
 - merge_diff_mode: fold all merge diff variants into an enum
 - combine-diff: do not pass revs->dense_combined_merges redundantly
 - merge-recursive: -Xindex-only to leave worktree unchanged
 - merge-recursive: internal flag to avoid touching the worktree
 - merge-recursive: remove dead conditional in update_stages()

 "log -p" output learns a new way to let users inspect a merge
 commit by showing the differences between the automerged result
 with conflicts the person who recorded the merge would have seen
 and the final conflict resolution that was recorded in the merge.

 Waiting for a reroll ($gmane/256591).


* hv/submodule-config (2014-11-11) 4 commits
 - do not die on error of parsing fetchrecursesubmodules option
 - use new config API for worktree configurations of submodules
 - extract functions for submodule config set and lookup
 - implement submodule config cache for lookup of submodule names

 Kicked back to 'pu' per request ($gmane/255610).


* ab/add-interactive-show-diff-func-name (2014-05-12) 2 commits
 - SQUASH??? git-add--interactive: Preserve diff heading when splitting hunks
 - git-add--interactive: Preserve diff heading when splitting hunks

 Waiting for a reroll.


* jn/gitweb-utf8-in-links (2014-05-27) 1 commit
 - gitweb: Harden UTF-8 handling in generated links

 $gmane/250758?


* ss/userdiff-update-csharp-java (2014-06-02) 2 commits
 - userdiff: support Java try keyword
 - userdiff: support C# async methods and correct C# keywords

 Reviews sent; waiting for a response.


* bg/rebase-off-of-previous-branch (2014-04-16) 1 commit
 - git-rebase: print name of rev when using shorthand

 Teach "git rebase -" to report the concrete name of the branch
 (i.e. the previous one).

 But it stops short and does not do the same for "git rebase @{-1}".
 Expecting a reroll.


* rb/merge-prepare-commit-msg-hook (2014-01-10) 4 commits
 - merge: drop unused arg from abort_commit method signature
 - merge: make prepare_to_commit responsible for write_merge_state
 - t7505: ensure cleanup after hook blocks merge
 - t7505: add missing &&

 Expose more merge states (e.g. $GIT_DIR/MERGE_MODE) to hooks that
 run during "git merge".  The log message stresses too much on one
 hook, prepare-commit-msg, but it would equally apply to other hooks
 like post-merge, I think.

 Waiting for a reroll.


* jc/graph-post-root-gap (2013-12-30) 3 commits
 - WIP: document what we want at the end
 - graph: remove unused code a bit
 - graph: stuff the current commit into graph->columns[]

 This was primarily a RFH ($gmane/239580).


* tg/perf-lib-test-perf-cleanup (2013-09-19) 2 commits
 - perf-lib: add test_perf_cleanup target
 - perf-lib: split starting the test from the execution

 Add test_perf_cleanup shell function to the perf suite, that allows
 the script writers to define a test with a clean-up action.

 Will hold.


* jc/show-branch (2014-03-24) 5 commits
 - show-branch: use commit slab to represent bitflags of arbitrary width
 - show-branch.c: remove "all_mask"
 - show-branch.c: abstract out "flags" operation
 - show-branch.c: lift all_mask/all_revs to a global static
 - show-branch.c: update comment style

 Waiting for the final step to lift the hard-limit before sending it out.

--------------------------------------------------
[Cooking]

* bb/update-unicode-table (2014-12-22) 5 commits
  (merged to 'next' on 2014-12-23 at b4ce669)
 + update_unicode.sh: delete the command group
 + update_unicode.sh: make the output structure visible
 + update_unicode.sh: shorten uniset invocation path
 + update_unicode.sh: set UNICODE_DIR only once
 + update_unicode.sh: simplify output capture

 Simplify the procedure to generate unicode table.

 Will merge to 'master'.


* bc/fetch-thin-less-aggressive-in-normal-repository (2014-12-29) 3 commits
 - pack-objects: use --objects-edge-aggressive for shallow repos
 - rev-list: add an option to mark fewer edges as uninteresting
 - Documentation: add missing article in rev-list-options.txt

 Earlier we made "rev-list --object-edge" more aggressively list the
 objects at the edge commits, in order to reduce number of objects
 fetched into a shallow repository, but the change affected cases
 other than "fetching into a shallow repository" and made it
 unusably slow (e.g. fetching into a normal repository should not
 have to suffer the overhead from extra processing).  Limit it to a
 more specific case by introducing --objects-edge-aggressive, a new
 option to rev-list.

 Will merge to 'next'.


* es/squelch-openssl-warnings-on-macosx (2014-12-18) 1 commit
  (merged to 'next' on 2014-12-23 at e88cf6a)
 + git-compat-util: suppress unavoidable Apple-specific deprecation warnings

 Squelch useless compiler warnings on Mac OS X.

 Will merge to 'master'.


* jh/pre-push-sample-no-custom-ifs (2014-12-22) 1 commit
  (merged to 'next' on 2014-12-29 at c516021)
 + pre-push.sample: remove unnecessary and misleading IFS=' '

 The sample pre-push hook used customized IFS=' ' for no good reason.

 Will merge to 'master'.


* sb/atomic-push (2014-12-22) 7 commits
 - t5543-atomic-push.sh: add basic tests for atomic pushes
 - push.c: add an --atomic argument
 - receive-pack: move execute_commands_non_atomic before execute_commands
 - receive-pack.c: receive-pack.c: use a single ref_transaction for atomic pushes
 - send-pack.c: add --atomic command line argument
 - send-pack: rename ref_update_to_be_sent to check_to_send_update
 - receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses mh/reflog-expire.)

 "git push" has been taught a "--atomic" option that makes push to
 update more than one ref an "all-or-none" affair.


* sb/dco-indentation-fix (2014-12-22) 1 commit
  (merged to 'next' on 2014-12-23 at c865690)
 + Documentation/SubmittingPatches: unify whitespace/tabs for the DCO

 Will merge to 'master'.


* sb/t5400-remove-unused (2014-12-16) 1 commit
  (merged to 'next' on 2014-12-23 at a992011)
 + t5400: remove dead code

 Will merge to 'master'.


* tf/prompt-preserve-exit-status (2014-12-22) 1 commit
  (merged to 'next' on 2014-12-23 at dfcd89f)
 + git-prompt: preserve value of $? inside shell prompt

 Using the exit status of the last command in the prompt, e.g.
 PS1='$(__git_ps1) $? ', did not work well because the helper
 function stomped on the exit status.

 Will merge to 'master'.


* ye/http-accept-language (2014-12-22) 1 commit
 - http: Add Accept-Language header if possible

 Expecting a reroll ($gmane/261810).


* jk/strbuf-doc-to-header (2014-12-12) 4 commits
 - strbuf.h: reorganize api function grouping headers
 - strbuf.h: format asciidoc code blocks as 4-space indent
 - strbuf.h: drop asciidoc list formatting from API docs
 - strbuf: migrate api-strbuf.txt documentation to strbuf.h

 Resolve the "doc vs header" to favor the latter.

 Expecting to be rerolled.


* mh/reflog-expire (2014-12-22) 24 commits
 - refs.c: let fprintf handle the formatting
 - refs.c: don't expose the internal struct ref_lock in the header file
 - lock_any_ref_for_update(): inline function
 - refs.c: remove unlock_ref/close_ref/commit_ref from the refs api
 - reflog_expire(): new function in the reference API
 - expire_reflog(): treat the policy callback data as opaque
 - Move newlog and last_kept_sha1 to "struct expire_reflog_cb"
 - expire_reflog(): move rewrite to flags argument
 - expire_reflog(): move verbose to flags argument
 - expire_reflog(): pass flags through to expire_reflog_ent()
 - struct expire_reflog_cb: a new callback data type
 - Rename expire_reflog_cb to expire_reflog_policy_cb
 - expire_reflog(): move updateref to flags argument
 - expire_reflog(): move dry_run to flags argument
 - expire_reflog(): add a "flags" argument
 - expire_reflog(): extract two policy-related functions
 - Extract function should_expire_reflog_ent()
 - expire_reflog(): use a lock_file for rewriting the reflog file
 - expire_reflog(): return early if the reference has no reflog
 - expire_reflog(): rename "ref" parameter to "refname"
 - expire_reflog(): it's not an each_ref_fn anymore
 - refs.c: add a function to append a reflog entry to a fd
 - refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 - refs.c: make ref_transaction_create a wrapper for ref_transaction_update
 (this branch is used by sb/atomic-push.)

 Restructure "reflog expire" to fit the reflogs better with the
 recently updated ref API.

 Looked reasonable (except that some shortlog entries stood out like
 a sore thumb).


* po/doc-core-ignorestat (2014-12-12) 1 commit
  (merged to 'next' on 2014-12-23 at d2b3e84)
 + doc: core.ignoreStat clarify the --assume-unchanged effect

 Will merge to 'master'.


* jk/add-i-read-error (2014-12-15) 1 commit
  (merged to 'next' on 2014-12-23 at 9b76001)
 + add--interactive: leave main loop on read error

 "git add -i" did not notice when the interactive command input
 stream went away and kept asking.

 Will merge to 'master'.


* pd/completion-filenames-fix (2014-12-15) 1 commit
  (merged to 'next' on 2014-12-23 at e2b10ab)
 + Update documentation occurrences of filename .sh

 The top-of-the-file instruction for completion scripts (in contrib/)
 did not name the files correctly.

 Will merge to 'master'.


* rd/send-email-2047-fix (2014-12-15) 2 commits
  (merged to 'next' on 2014-12-23 at 2b101ce)
 + send-email: handle adjacent RFC 2047-encoded words properly
 + send-email: align RFC 2047 decoding more closely with the spec

 "git send-email" did not handle RFC 2047 encoded headers quite
 right.

 Will merge to 'master'.


* jn/doc-api-errors (2014-12-04) 1 commit
 - doc: document error handling functions and conventions

 For discussion.


* jn/rerere-fail-on-auto-update-failure (2014-12-03) 2 commits
 - SQUASH???
 - rerere: error out on autoupdate failure

 Will be rerolled as a part of a larger series.


* jc/push-to-checkout (2014-12-01) 2 commits
 - receive-pack: support push-to-checkout hook
 - receive-pack: refactor updateInstead codepath

 Extending the js/push-to-deploy topic, the behaviour of "git push"
 when updating the working tree and the index with an update to the
 branch that is checked out can be tweaked by push-to-checkout hook.

 Needs docs.


* lh/send-email-hide-x-mailer (2014-12-15) 2 commits
  (merged to 'next' on 2014-12-23 at fc16c68)
 + test/send-email: --[no-]xmailer tests
 + send-email: add --[no-]xmailer option

 "git send-email" normally identifies itself via X-Mailer: header
 in the message it sends out.  A new command line flag allows the
 header to be squelched.

 Will merge to 'master'.


* nd/list-files (2014-12-01) 19 commits
 - list-files: -M aka diff-cached
 - list-files -F: show submodules with the new indicator '&'
 - list-files: add -F/--classify
 - list-files: show directories as well as files
 - list-files: do not show duplicate cached entries
 - list-files: sort output and remove duplicates
 - list-files: add -t back
 - list-files: add -1 short for --no-column
 - list-files: add -R/--recursive short for --max-depth=-1
 - list-files: -u does not imply showing stages
 - list-files: a user friendly version of ls-files and more
 - ls-files: support --max-depth
 - ls-files: add --column
 - ls-files: add --color to highlight file names
 - ls-files: buffer full item in strbuf before printing
 - ls_colors.c: highlight submodules like directories
 - ls_colors.c: add a function to color a file name
 - ls_colors.c: parse color.ls.* from config file
 - ls_colors.c: add $LS_COLORS parsing code

 A new "git list-files" Porcelain command, "ls-files" with bells and
 whistles.


* nd/multiple-work-trees (2014-12-01) 34 commits
 - git-common-dir: make "modules/" per-working-directory directory
 - checkout: do not fail if target is an empty directory
 - t2025: add a test to make sure grafts is working from a linked checkout
 - checkout: don't require a work tree when checking out into a new one
 - git_path(): keep "info/sparse-checkout" per work-tree
 - count-objects: report unused files in $GIT_DIR/worktrees/...
 - gc: support prune --worktrees
 - gc: factor out gc.pruneexpire parsing code
 - gc: style change -- no SP before closing parenthesis
 - checkout: clean up half-prepared directories in --to mode
 - checkout: reject if the branch is already checked out elsewhere
 - prune: strategies for linked checkouts
 - checkout: support checking out into a new working directory
 - use new wrapper write_file() for simple file writing
 - wrapper.c: wrapper to open a file, fprintf then close
 - setup.c: support multi-checkout repo setup
 - setup.c: detect $GIT_COMMON_DIR check_repository_format_gently()
 - setup.c: convert check_repository_format_gently to use strbuf
 - setup.c: detect $GIT_COMMON_DIR in is_git_directory()
 - setup.c: convert is_git_directory() to use strbuf
 - git-stash: avoid hardcoding $GIT_DIR/logs/....
 - *.sh: avoid hardcoding $GIT_DIR/hooks/...
 - git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects
 - $GIT_COMMON_DIR: a new environment variable
 - commit: use SEQ_DIR instead of hardcoding "sequencer"
 - fast-import: use git_path() for accessing .git dir instead of get_git_dir()
 - reflog: avoid constructing .lock path with git_path
 - *.sh: respect $GIT_INDEX_FILE
 - git_path(): be aware of file relocation in $GIT_DIR
 - path.c: group git_path(), git_pathdup() and strbuf_git_path() together
 - path.c: rename vsnpath() to do_git_path()
 - git_snpath(): retire and replace with strbuf_git_path()
 - path.c: make get_pathname() call sites return const char *
 - path.c: make get_pathname() return strbuf instead of static buffer

 A replacement for contrib/workdir/git-new-workdir that does not
 rely on symbolic links and make sharing of objects and refs safer
 by making the borrowee and borrowers aware of each other.


* sb/copy-fd-errno (2014-11-17) 1 commit
 - copy.c: make copy_fd preserve meaningful errno

 Will be rerolled as a part of a larger series.


* jk/approxidate-avoid-y-d-m-over-future-dates (2014-11-13) 2 commits
  (merged to 'next' on 2014-12-15 at 397e986)
 + approxidate: allow ISO-like dates far in the future
 + pass TIME_DATE_NOW to approxidate future-check

 Traditionally we tried to avoid interpreting date strings given by
 the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
 used early November 2014 was taken as "October 12, 2014" because it
 is likely that a date in the future, December 10, is a mistake.

 Loosen this and do not tiebreak by future-ness of the date when

 (1) ISO-like format is used, and
 (2) the string can make sense interpreted as both y-m-d and y-d-m.

 Will merge to 'master'.


* br/imap-send-verbosity (2014-11-05) 1 commit
  (merged to 'next' on 2014-12-15 at 504af0b)
 + imap-send: use parse options API to determine verbosity
 (this branch is used by br/imap-send-via-libcurl.)

 Will merge to 'master'.


* br/imap-send-via-libcurl (2014-11-10) 1 commit
  (merged to 'next' on 2014-12-15 at 90db637)
 + git-imap-send: use libcurl for implementation
 (this branch uses br/imap-send-verbosity.)

 Newer libCurl knows how to talk IMAP; "git imap-send" has been
 updated to use this instead of a hand-rolled OpenSSL calls.

 Will merge to 'master'.


* nd/lockfile-absolute (2014-11-03) 1 commit
  (merged to 'next' on 2014-12-15 at 34db9af)
 + lockfile.c: store absolute path

 The lockfile API can get confused which file to clean up when the
 process moved the $cwd after creating a lockfile.

 Will merge to 'master'.


* jc/merge-bases (2014-10-30) 2 commits
  (merged to 'next' on 2014-12-15 at cac279e)
 + get_merge_bases(): always clean-up object flags
 + bisect: clean flags after checking merge bases

 The get_merge_bases*() API was easy to misuse by careless
 copy&paste coders, leaving object flags tainted in the commits that
 needed to be traversed.

 Will merge to 'master'.


* jc/strbuf-add-lines-avoid-sp-ht-sequence (2014-10-27) 1 commit
  (merged to 'next' on 2014-12-15 at b499889)
 + strbuf_add_commented_lines(): avoid SP-HT sequence in commented lines

 The commented output used to blindly add a SP before the payload
 line, resulting in "# \t<indented text>\n" when the payload began
 with a HT.  Instead, produce "#\t<indented text>\n".

 Will merge to 'master'.


* nd/untracked-cache (2014-12-15) 24 commits
 - SQUASH???
 - untracked cache: guard and disable on system changes
 - mingw32: add uname()
 - t7063: tests for untracked cache
 - update-index: test the system before enabling untracked cache
 - update-index: manually enable or disable untracked cache
 - status: enable untracked cache
 - untracked-cache: temporarily disable with $GIT_DISABLE_UNTRACKED_CACHE
 - untracked cache: mark index dirty if untracked cache is updated
 - untracked cache: print stats with $GIT_TRACE_UNTRACKED_STATS
 - untracked cache: avoid racy timestamps
 - read-cache.c: split racy stat test to a separate function
 - untracked cache: invalidate at index addition or removal
 - untracked cache: load from UNTR index extension
 - untracked cache: save to an index extension
 - ewah: add convenient wrapper ewah_serialize_strbuf()
 - untracked cache: don't open non-existent .gitignore
 - untracked cache: mark what dirs should be recursed/saved
 - untracked cache: record/validate dir mtime and reuse cached output
 - untracked cache: make a wrapper around {open,read,close}dir()
 - untracked cache: invalidate dirs recursively if .gitignore changes
 - untracked cache: initial untracked cache validation
 - untracked cache: record .gitignore information and dir hierarchy
 - dir.c: optionally compute sha-1 of a .gitignore file

 Comments?


* jc/diff-b-m (2014-10-23) 1 commit
  (merged to 'next' on 2014-12-15 at 59c6636)
 + diff -B -M: fix output for "copy and then rewrite" case

 Fix long-standing bug in "diff -B -M" output.

 Will merge to 'master'.


* jc/checkout-local-track-report (2014-10-14) 1 commit
  (merged to 'next' on 2014-12-15 at e91a7df)
 + checkout: report upstream correctly even with loosely defined branch.*.merge

 The report from "git checkout" on a branch that builds on another
 local branch by setting its branch.*.merge to branch name (not a
 full refname) incorrectly said that the upstream is gone.

 Will merge to 'master'.


* jc/clone-borrow (2014-10-15) 1 commit
  (merged to 'next' on 2014-12-15 at 08fdf77)
 + clone: --dissociate option to mark that reference is only temporary

 Allow "git clone --reference" to be used more safely.

 Will merge to 'master'.

--------------------------------------------------
[Discarded]

* mb/enable-lib-terminal-test-on-newer-darwin (2014-11-14) 1 commit
 . t/lib-terminal: allow TTY tests to run under recent Mac OS

 We probably should drop this ($gmane/259609).


* zk/grep-color-words (2014-10-27) 2 commits
 . Revert "grep: fix match highlighting for combined patterns with context lines"
 . grep: fix match highlighting for combined patterns with context lines

 rs/grep-color-words topic solves it in a different way.

 Will discard.


* jn/dedup-doc-header (2014-12-10) 2 commits
 . put string-list API documentation in one place
 . put strbuf API documentation in one place

 We would want to have an easy way for developers to learn about
 APIs, and also a way to encourage them to keep the API
 documentation up to date when they make changes.  Having header
 comments and API documentation duplicated in two different places
 risked them going out of sync.

 The approach taken by jk/strbuf-doc-to-header is the other way
 around, which people seem to prefer, so this is discarded.


* jt/timer-settime (2014-08-29) 6 commits
 . use timer_settime() for new platforms
 . autoconf: check for timer_settime()
 . autoconf: check for struct itimerspec
 . autoconf: check for struct sigevent
 . autoconf: check for struct timespec
 . autoconf: check for timer_t

 Was wanting for a reroll.


* rs/ref-transaction-reflog (2014-11-03) 15 commits
 . refs.c: allow deleting refs with a broken sha1
 . refs.c: remove lock_any_ref_for_update
 . refs.c: make unlock_ref/close_ref/commit_ref static
 . refs.c: rename log_ref_setup to create_reflog
 . reflog.c: use a reflog transaction when writing during expire
 . refs.c: allow multiple reflog updates during a single transaction
 . refs.c: only write reflog update if msg is non-NULL
 . refs.c: add a flag to allow reflog updates to truncate the log
 . refs.c: add a transaction function to append a reflog entry
 . copy.c: make copy_fd preserve meaningful errno
 . refs.c: add a function to append a reflog entry to a fd
 . refs.c: add a new update_type field to ref_update
 . refs.c: rename the transaction functions
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c make ref_transaction_create a wrapper to ref_transaction_update
 (this branch is used by rs/ref-transaction-rename and rs/ref-transaction-send-pack.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-rename (2014-11-07) 16 commits
 . refs.c: add an err argument to pack_refs
 . refs.c: make lock_packed_refs take an err argument
 . refs.c: make add_packed_ref return an error instead of calling die
 . refs.c: replace the onerr argument in update_ref with a strbuf err
 . refs.c: make the *_packed_refs functions static
 . refs.c: make repack_without_refs static
 . remote.c: use a transaction for deleting refs
 . refs.c: write updates to packed refs when a transaction has more than one ref
 . refs.c: move reflog updates into its own function
 . refs.c: rollback the lockfile before we die() in repack_without_refs
 . refs.c: update rename_ref to use a transaction
 . refs.c: add transaction support for renaming a reflog
 . refs.c: use a stringlist for repack_without_refs
 . refs.c: use packed refs when deleting refs during a transaction
 . refs.c: return error instead of dying when locking fails during transaction
 . refs.c: allow passing raw git_committer_info as email to _update_reflog
 (this branch is used by rs/ref-transaction-send-pack; uses rs/ref-transaction-reflog.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* rs/ref-transaction-send-pack (2014-11-07) 7 commits
 . refs.c: add an err argument to create_symref
 . refs.c: add an err argument to create_reflog
 . t5543-atomic-push.sh: add basic tests for atomic pushes
 . push.c: add an --atomic-push argument
 . receive-pack.c: use a single transaction when atomic-push is negotiated
 . send-pack.c: add an --atomic-push command line argument
 . receive-pack.c: add protocol support to negotiate atomic-push
 (this branch uses rs/ref-transaction-reflog and rs/ref-transaction-rename.)

 Stefan Beller started working on reorganizing these three series,
 which unfortunately did not see much reviews.


* sb/simplify-repack-without-refs (2014-11-20) 1 commit
 . refs.c: use a string_list for repack_without_refs


* sb/log-ref-write-fd (2014-11-20) 1 commit
 . refs.c: add a function to append a reflog entry to a fd

 Will be rerolled as a part of a larger series.


* sb/ref-transaction-unify-to-update (2014-11-20) 2 commits
 . refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
 . refs.c: make ref_transaction_create a wrapper for ref_transaction_update
 (this branch is used by sb/ref-transaction-reflog.)

 Code simplification.

 Will be rerolled as a part of a larger series.


* sb/write-sha1-update-reflog (2014-11-24) 1 commit
 . refs.c: move reflog updates into its own function

 Moves a part of function around to add a helper that still only has
 one caller.  Need to see how this helps in a bigger picture.


* sb/ref-transaction-reflog (2014-12-03) 2 commits
 . refs.c: rename transaction.updates to transaction.ref_updates
 . refs.c: rename the transaction functions
 (this branch uses sb/ref-transaction-unify-to-update.)

 Will be rerolled as a part of a larger series.

^ permalink raw reply	[relevance 3%]

* [ANNOUNCE] Git v2.3.0-rc0
@ 2015-01-12 23:57  1% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-01-12 23:57 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

An early preview release Git v2.3.0-rc0 is now available for
testing at the usual places.

With the slowness from the end-of-year holiday, this cycle turned
out to be a relatively lean one as I predicted (just 200 changes
since 2.2, as opposed to ~500 changes in an normal cycle), but that
is fine.  From time to time it is OK to have a release that does not
add many new things but just fixes niggles here and there.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/testing/

The following public repositories all have a copy of the 'v2.3.0-rc0'
tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v2.3 Release Notes (draft)
==============================

Updates since v2.2
------------------

Ports

 * Recent gcc toolchain on Cygwin started throwing compilation warning,
   which has been squelched.


UI, Workflows & Features

 * It was cumbersome to use "GIT_SSH" mechanism when the user wanted
   to pass an extra set of arguments to the underlying ssh.  A new
   environment variable GIT_SSH_COMMAND can be used for this.

 * A request to store an empty note via "git notes" meant to remove
   note from the object but with --allow-empty we will store a
   (surprise!)  note that is empty.

 * "git interpret-trailers" learned to properly handle the
   "Conflicts:" block at the end.

 * "git am" learned "--message-id" option to copy the message ID of
   the incoming e-mail to the log message of resulting commit.

 * "git clone --reference=<over there>" learned the "--dissociate"
   option to go with it; it borrows objects from the reference object
   store while cloning only to reduce network traffic and then
   dissociates the resulting clone from the reference by performing
   local copies of borrowed objects.

 * "git send-email" learned "--transfer-encoding" option to force a
   non-fault Content-Transfer-Encoding header (e.g. base64).

 * "git send-email" normally identifies itself via X-Mailer: header in
   the message it sends out.  A new command line flag --no-xmailer
   allows the user to squelch the header.

 * "git push" into a repository with a working tree normally refuses
   to modify the branch that is checked out.  The command learned to
   optionally do an equivalent of "git reset --hard" only when there
   is no change to the working tree and the index instead, which would
   be useful to "deploy" by pushing into a repository.

 * "git new-workdir" (in contrib/) can be used to populate an empty
   and existing directory now.

 * Credential helpers are asked in turn until one of them give
   positive response, which is cumbersome to turn off when you need to
   run Git in an automated setting.  The credential helper interface
   learned to allow a helper to say "stop, don't ask other helpers."
   Also GIT_TERMINAL_PROMPT environment can be set to false to disable
   our built-in prompt mechanism for passwords.

 * "git branch -d" (delete) and "git branch -m" (move) learned to
   honor "-f" (force) flag; unlike many other subcommands, the way to
   force these have been with separate "-D/-M" options, which was
   inconsistent.

 * "diff-highlight" filter (in contrib/) allows its color output to be
   customized via configuration variables.

 * "git imap-send" learned to take "-v" (verbose) and "-q" (quiet)
   command line options.

 * "git imap-send" now can be built to use cURL library to talk to
   IMAP servers (if the library is recent enough, of course).
   This allows you to use authenticate method other than CRAM-MD5,
   among other things.


Performance, Internal Implementation, Development Support etc.

 * Earlier we made "rev-list --object-edge" more aggressively list the
   objects at the edge commits, in order to reduce number of objects 
   fetched into a shallow repository, but the change affected cases
   other than "fetching into a shallow repository" and made it
   unusably slow (e.g. fetching into a normal repository should not
   have to suffer the overhead from extra processing).  Limit it to a
   more specific case by introducing --objects-edge-aggressive, a new
   option to rev-list.

 * Squelched useless compiler warnings on Mac OS X regarding the
   crypto API.

 * The procedure to generate unicode table has been simplified.

 * Some filesystems assign filemodes in a strange way, fooling then
   automatic "filemode trustability" check done during a new
   repository creation.  The initialization codepath has been hardened
   against this issue.

 * The codepath in "git remote update --prune" to drop many refs has
   been optimized.

 * The API into get_merge_bases*() family of functions was easy to
   misuse, which has been corrected to make it harder to do so.

 * Long overdue departure from the assumption that S_IFMT is shared by
   everybody made in 2005, which was necessary to port to z/OS.

 * "git push" and "git fetch" did not communicate an overlong refname
   correctly.  Now it uses 64kB sideband to accommodate longer ones.

 * Recent GPG changes the keyring format and drops support for RFC1991
   formatted signatures, breaking our existing tests.

 * "git-prompt" (in contrib/) used a variable from the global scope,
   possibly contaminating end-user's namespace.


Also contains various documentation updates and code clean-ups.


Fixes since v2.2
----------------

Unless otherwise noted, all the fixes since v2.2 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * The logic in "git bisect bad HEAD" etc. to avoid forcing the test
   of the common ancestor of bad and good commits was broken.
   (merge 07913d5 cc/bisect-rev-parsing later to maint).

 * "git checkout-index --temp=$target $path" did not work correctly
   for paths outside the current subdirectory in the project.
   (merge 74c4de5 es/checkout-index-temp later to maint).

 * The report from "git checkout" on a branch that builds on another
   local branch by setting its branch.*.merge to branch name (not a
   full refname) incorrectly said that the upstream is gone.
   (merge 05e7368 jc/checkout-local-track-report later to maint).

 * With The git-prompt support (in contrib/), using the exit status of
   the last command in the prompt, e.g.  PS1='$(__git_ps1) $? ', did
   not work well, because the helper function stomped on the exit
   status.
   (merge eb443e3 tf/prompt-preserve-exit-status later to maint).


 * Recent update to "git commit" broke amending an existing commit
   with bogus author/committer lines without a valid e-mail address.
   (merge c83a509 jk/commit-date-approxidate later to maint).

 * The lockfile API used to get confused which file to clean up when
   the process moved the $cwd after creating a lockfile.
   (merge fa137f6 nd/lockfile-absolute later to maint).

 * Traditionally we tried to avoid interpreting date strings given by
   the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
   used early November 2014 was taken as "October 12, 2014" because it
   is likely that a date in the future, December 10, is a mistake.
   This heuristics has been loosened to allow people to express future
   dates (most notably, --until=<date> may want to be far in the
   future) and we no longer tiebreak by future-ness of the date when

    (1) ISO-like format is used, and
    (2) the string can make sense interpreted as both y-m-d and y-d-m.

   Git may still have to use the heuristics to tiebreak between dd/mm/yy
   and mm/dd/yy, though.
   (merge d372395 jk/approxidate-avoid-y-d-m-over-future-dates later to maint).

 * Git did not correctly read an overlong refname from a packed refs
   file.
   (merge ea41783 jk/read-packed-refs-without-path-max later to maint).

 * "git apply" was described in the documentation to take --ignore-date
   option, which it does not.
   (merge 0cef4e7 rw/apply-does-not-take-ignore-date later to maint).

 * "git add -i" did not notice when the interactive command input
   stream went away and kept asking the same question.
   (merge a8bec7a jk/add-i-read-error later to maint).

 * "git send-email" did not handle RFC 2047 encoded headers quite
   right.
   (merge ab47e2a rd/send-email-2047-fix later to maint).

 * New tag object format validation added in 2.2 showed garbage after
   a tagname it reported in its error message.
   (merge a1e920a js/fsck-tag-validation later to maint).

 * The code that reads the reflog from the newer to the older entries
   did not handle an entry that crosses a boundary of block it uses to
   read them correctly.
   (merge 69216bf jk/for-each-reflog-ent-reverse later to maint).

 * "git diff -B -M" after making a new copy B out of an existing file
   A and then editing A extensively ought to report that B was created
   by copying A and A was modified, which is what "git diff -C"
   reports, but it instead said A was renamed to B and A was edited
   heavily in place.  This was not just incoherent but also failed to
   apply with "git apply".  The report has been corrected to match what
   "git diff -C" produces for this case.
   (merge 6936b58 jc/diff-b-m later to maint).

 * In files we pre-populate for the user to edit with commented hints,
   a line of hint that is indented with a tab used to show as '#' (or
   any comment char), ' ' (space), and then the hint text that began
   with the tab, which some editors flag as an indentation error (tab
   following space).  We now omit the space after the comment char in
   such a case.
   (merge d55aeb7 jc/strbuf-add-lines-avoid-sp-ht-sequence later to maint).

 * "git ls-tree" does not support path selection based on negative
   pathspecs, but did not error out when negative pathspecs are given.
   (merge f1f6224 nd/ls-tree-pathspec later to maint).

 * The function sometimes returned a non-freeable memory and some
   other times returned a piece of memory that must be freed, leading
   to inevitable leaks.
   (merge 59362e5 jc/exec-cmd-system-path-leak-fix later to maint).

 * The code to abbreviate an object name to its short unique prefix
   has been optimized when no abbreviation was requested.
   (merge 61e704e mh/find-uniq-abbrev later to maint).

 * "git add --ignore-errors ..." did not ignore an error to
   give a file that did not exist.
   (merge 1d31e5a mg/add-ignore-errors later to maint).

 * "git checkout $treeish $path", when $path in the index and the
   working tree already matched what is in $treeish at the $path,
   still overwrote the $path unnecessarily.
   (merge c5326bd jk/checkout-from-tree later to maint).

 * "git config --get-color" did not parse its command line arguments
   carefully.
   (merge cb35722 jk/colors-fix later to maint).

 * open() emulated on Windows platforms did not give EISDIR upon
   an attempt to open a directory for writing.
   (merge ba6fad0 js/windows-open-eisdir-error later to maint).

 * A few code paths used abs() when they should have used labs() on
   long integers.
   (merge 83915ba rs/maint-config-use-labs later to maint).
   (merge 31a8aa1 rs/receive-pack-use-labs later to maint).

 * "gitweb" used to depend on a behaviour recent CGI.pm deprecated.
   (merge 13dbf46 jk/gitweb-with-newer-cgi-multi-param later to maint).

 * "git init" (hence "git clone") initialized the per-repository
   configuration file .git/config with x-bit by mistake.
   (merge 1f32ecf mh/config-flip-xbit-back-after-checking later to maint).

 * Git 2.0 was supposed to make the "simple" mode for the default of
   "git push", but it didn't.
   (merge 00a6fa0 jk/push-simple later to maint).

 * "Everyday" document had a broken link.
   (merge 366c8d4 po/everyday-doc later to maint).

 * A few test fixes.
   (merge 880ef58 jk/no-perl-tests later to maint).

 * The build procedure did not bother fixing perl and python scripts
   when NO_PERL and NO_PYTHON build-time configuration changed.
   (merge ca2051d jk/rebuild-perl-scripts-with-no-perl-seting-change later to maint).

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

Changes since v2.2.0 are as follows:

Alexander Kuleshov (1):
      clean: typofix

Alfred Perlstein (1):
      git-svn: support for git-svn propset

Beat Bolli (5):
      update_unicode.sh: simplify output capture
      update_unicode.sh: set UNICODE_DIR only once
      update_unicode.sh: shorten uniset invocation path
      update_unicode.sh: make the output structure visible
      update_unicode.sh: delete the command group

Ben Walton (1):
      t0090: tweak awk statement for Solaris /usr/xpg4/bin/awk

Bernhard Reiter (2):
      imap-send: use parse options API to determine verbosity
      git-imap-send: use libcurl for implementation

Christian Couder (5):
      commit: make ignore_non_trailer() non static
      trailer: reuse ignore_non_trailer() to ignore conflict lines
      trailer: add test with an old style conflict block
      bisect: parse revs before passing them to check_expected_revs()
      bisect: add test to check that revs are properly parsed

Christian Hesse (4):
      tests: create gpg homedir on the fly
      tests: skip RFC1991 tests for gnupg 2.1
      tests: replace binary GPG keyrings with ASCII-armored keys
      tests: make comment on GPG keyring match the code

Dan Wyand (1):
      git-sh-setup.sh: use dashdash with basename call

David Aguilar (4):
      mergetool--lib: remove use of $status global
      difftool--helper: add explicit exit statement
      mergetool: simplify conditionals
      mergetools: stop setting $status in merge_cmd()

David Michael (1):
      compat: convert modes to use portable file type values

Eric Sunshine (7):
      git-compat-util: suppress unavoidable Apple-specific deprecation warnings
      t2004: modernize style
      t2004: drop unnecessary write-tree/read-tree
      t2004: standardize file naming in symlink test
      t2004: demonstrate broken relative path printing
      checkout-index: fix --temp relative path mangling
      SubmittingPatches: explain rationale for using --notes with format-patch

Hartmut Henkel (1):
      l10n: de.po: fix typos

Jeff King (38):
      pass TIME_DATE_NOW to approxidate future-check
      checkout $tree: do not throw away unchanged index entries
      approxidate: allow ISO-like dates far in the future
      Makefile: have perl scripts depend on NO_PERL setting
      t0090: mark add-interactive test with PERL prerequisite
      t960[34]: mark cvsimport tests as requiring perl
      gitweb: hack around CGI's list-context param() handling
      docs: describe ANSI 256-color mode
      config: fix parsing of "git config --get-color some.key -1"
      t4026: test "normal" color
      parse_color: refactor color storage
      parse_color: support 24-bit RGB values
      parse_color: recognize "no$foo" to clear the $foo attribute
      diff-highlight: allow configurable colors
      push: truly use "simple" as default, not "upstream"
      credential: let helpers tell us to quit
      prompt: respect GIT_TERMINAL_PROMPT to disable terminal prompts
      for_each_reflog_ent_reverse: fix newlines on block boundaries
      for_each_reflog_ent_reverse: turn leftover check into assertion
      fsck: properly bound "invalid tag name" error message
      parse_color: drop COLOR_BACKGROUND macro
      read_packed_refs: use a strbuf for reading lines
      read_packed_refs: pass strbuf to parse_ref_line
      read_packed_refs: use skip_prefix instead of static array
      pkt-line: allow writing of LARGE_PACKET_MAX buffers
      t: support clang/gcc AddressSanitizer
      commit: loosen ident checks when generating template
      commit: always populate GIT_AUTHOR_* variables
      add--interactive: leave main loop on read error
      unpack-trees: propagate errors adding entries to the index
      read-tree: add tests for confusing paths like ".." and ".git"
      verify_dotfile(): reject .git case-insensitively
      t1450: refactor ".", "..", and ".git" fsck tests
      fsck: notice .git case-insensitively
      utf8: add is_hfs_dotgit() helper
      read-cache: optionally disallow HFS+ .git variants
      fsck: complain about HFS+ ".git" aliases in trees
      is_hfs_dotgit: loosen over-eager match of \u{..47}

Jim Hill (1):
      pre-push.sample: remove unnecessary and misleading IFS=' '

Johan Herland (9):
      builtin/notes: fix premature failure when trying to add the empty blob
      t3301: verify that 'git notes' removes empty notes by default
      builtin/notes: improve naming
      builtin/notes: refactor note file path into struct note_data
      builtin/notes: simplify early exit code in add()
      builtin/notes: split create_note() to clarify add vs. remove logic
      builtin/notes: add --allow-empty, to allow storing empty notes
      notes: empty notes should be shown by 'git log'
      t3301: modernize style

Johannes Schindelin (5):
      receive-pack: add another option for receive.denyCurrentBranch
      test-hashmap: squelch gcc compiler warning
      path: add is_ntfs_dotgit() helper
      read-cache: optionally disallow NTFS .git variants
      fsck: complain about NTFS ".git" aliases in trees

Johannes Sixt (2):
      Windows: correct detection of EISDIR in mingw_open()
      t5000 on Windows: do not mistake "sh.exe" as "sh"

Jonathan Nieder (2):
      Makefile: simplify by using SCRIPT_{PERL,SH}_GEN macros
      Makefile: have python scripts depend on NO_PYTHON setting

Junio C Hamano (38):
      checkout: report upstream correctly even with loosely defined branch.*.merge
      clone: --dissociate option to mark that reference is only temporary
      diff -B -M: fix output for "copy and then rewrite" case
      builtin/merge.c: drop a parameter that is never used
      merge & sequencer: unify codepaths that write "Conflicts:" hint
      strbuf_add_commented_lines(): avoid SP-HT sequence in commented lines
      builtin/commit.c: extract ignore_non_trailer() helper function
      merge & sequencer: turn "Conflicts:" hint into a comment
      bisect: clean flags after checking merge bases
      get_merge_bases(): always clean-up object flags
      unpack_trees: plug leakage of o->result
      mergetool--lib: remove no-op assignment to $status from setup_user_tool
      SubmittingPatches: refer to t/README for tests
      t/README: justify why "! grep foo" is sufficient
      t9001: style modernisation phase #1
      t9001: style modernisation phase #2
      t9001: style modernisation phase #3
      t9001: style modernisation phase #4
      t9001: style modernisation phase #5
      system_path(): always return free'able memory to the caller
      t5516: more tests for receive.denyCurrentBranch=updateInstead
      run-command.c: retire unused run_hook_with_custom_index()
      t3102: document that ls-tree does not yet support negated pathspec
      t3102: style modernization
      Start post 2.2 cycle
      First batch for 2.3 cycle
      tests: squelch noise from GPG machinery set-up
      Second batch for 2.3 cycle
      Git 1.8.5.6
      Git 1.9.5
      Git 2.0.5
      Git 2.1.4
      Git 2.2.1
      Prepare for 2.2.2
      Third batch for 2.3 cycle
      Fourth batch for 2.3 cycle
      Git 2.2.2
      Git 2.3.0-rc0

Justin Guenther (1):
      git-prompt.sh: make $f local to __git_eread()

Karsten Blees (1):
      pack-bitmap: do not use gcc packed attribute

Luis Henriques (2):
      send-email: add --[no-]xmailer option
      test/send-email: --[no-]xmailer tests

Michael Haggerty (11):
      cmd_config(): make a copy of path obtained from git_path()
      create_default_files(): don't set u+x bit on $GIT_DIR/config
      prune_remote(): exit early if there are no stale references
      prune_remote(): initialize both delete_refs lists in a single loop
      prune_remote(): sort delete_refs_list references en masse
      repack_without_refs(): make the refnames argument a string_list
      prune_remote(): rename local variable
      prune_remote(): iterate using for_each_string_list_item()
      sort_string_list(): rename to string_list_sort()
      t1400: add some more tests of "update-ref --stdin"'s verify command
      update-ref: fix "verify" command with missing <oldvalue>

Michael J Gruber (5):
      add: ignore only ignored files
      t3200-branch: test -M
      check-ignore: clarify treatment of tracked files
      gitignore.txt: do not suggest assume-unchanged
      branch: allow -f with -m and -d

Mike Hommey (1):
      sha1_name: avoid unnecessary sha1 lookup in find_unique_abbrev

Nguyễn Thái Ngọc Duy (6):
      lockfile.c: store absolute path
      tree.c: update read_tree_recursive callback to pass strbuf as base
      ls-tree: remove path filtering logic in show_tree
      ls-tree: disable negative pathspec because it's not supported
      index-pack: terminate object buffers with NUL
      index-format.txt: add a missing closing quote

Onno Kortmann (1):
      Show number of TODO items for interactive rebase

Paolo Bonzini (4):
      git-send-email: delay creation of MIME headers
      git-send-email: add --transfer-encoding option
      git-mailinfo: add --message-id
      git-am: add --message-id/--no-message-id

Paul Smith (1):
      git-new-workdir: don't fail if the target directory is empty

Peter van der Does (1):
      Update documentation occurrences of filename .sh

Philip Oakley (1):
      doc: make clear --assume-unchanged's user contract

Ralf Thielow (3):
      builtin/push.c: fix description of --recurse-submodules option
      for-each-ref: correct spelling of Tcl in option description
      completion: add git-tag options

Ramsay Allan Jones (2):
      git-compat-util.h: don't define _XOPEN_SOURCE on cygwin
      t0050-*.sh: mark the rename (case change) test as passing

René Scharfe (8):
      use args member of struct child_process
      use labs() for variables of type long instead of abs()
      use labs() for variables of type long instead of abs()
      use strbuf_complete_line() for adding a newline if needed
      commit-tree: simplify parsing of option -S using skip_prefix()
      merge: release strbuf after use in suggest_conflicts()
      transport: simplify duplicating a substring in transport_get() using xmemdupz()
      refs: plug strbuf leak in lock_ref_sha1_basic()

Ronald Wampler (1):
      git-am.txt: --ignore-date flag is not passed to git-apply

Ronnie Sahlberg (1):
      lock_ref_sha1_basic: do not die on locking errors

Slavomir Vlcek (3):
      builtin: move builtin retrieval to get_builtin()
      apply: fix typo in an error message
      Documentation/git-stripspace: add synopsis for --comment-lines

Stefan Beller (5):
      string_list: document string_list_(insert,lookup)
      mailmap: use higher level string list functions
      string_list: remove string_list_insert_at_index() from its API
      t5400: remove dead code
      Documentation/SubmittingPatches: unify whitespace/tabs for the DCO

Thomas Quinot (1):
      git_connect: set ssh shell command in GIT_SSH_COMMAND

Tony Finch (1):
      git-prompt: preserve value of $? inside shell prompt

Torsten Bögershausen (2):
      init-db: improve the filemode trustability check
      t0027: check the eol conversion warnings

brian m. carlson (4):
      Documentation: change "gitlink" typo in git-push
      Documentation: add missing article in rev-list-options.txt
      rev-list: add an option to mark fewer edges as uninteresting
      pack-objects: use --objects-edge-aggressive for shallow repos

Роман Донченко (2):
      send-email: align RFC 2047 decoding more closely with the spec
      send-email: handle adjacent RFC 2047-encoded words properly

^ permalink raw reply	[relevance 1%]

* [ANNOUNCE] Git v2.3.2
@ 2015-03-06 23:11  3% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-03-06 23:11 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

The latest maintenance release Git v2.3.2 is now available at
the usual places.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/

The following public repositories all have a copy of the 'v2.3.2'
tag and the 'maint' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v2.3.2 Release Notes
========================

Fixes since v2.3.1
------------------

 * "update-index --refresh" used to leak when an entry cannot be
   refreshed for whatever reason.

 * "git fast-import" used to crash when it could not close and
   conclude the resulting packfile cleanly.

 * "git blame" died, trying to free an uninitialized piece of memory.

 * "git merge-file" did not work correctly in a subdirectory.

 * "git submodule add" failed to squash "path/to/././submodule" to
   "path/to/submodule".

 * In v2.2.0, we broke "git prune" that runs in a repository that
   borrows from an alternate object store.

 * Certain older vintages of cURL give irregular output from
   "curl-config --vernum", which confused our build system.

 * An earlier workaround to squelch unhelpful deprecation warnings
   from the complier on Mac OSX unnecessarily set minimum required
   version of the OS, which the user might want to raise (or lower)
   for other reasons.

 * Longstanding configuration variable naming rules has been added to
   the documentation.

 * The credential helper for Windows (in contrib/) used to mishandle
   a user name with an at-sign in it.

 * Older GnuPG implementations may not correctly import the keyring
   material we prepare for the tests to use.

 * Clarify in the documentation that "remote.<nick>.pushURL" and
   "remote.<nick>.URL" are there to name the same repository accessed
   via different transports, not two separate repositories.

 * The pack bitmap support did not build with older versions of GCC.

 * Reading configuration from a blob object, when it ends with a lone
   CR, use to confuse the configuration parser.

 * We didn't format an integer that wouldn't fit in "int" but in
   "uintmax_t" correctly.

 * "git push --signed" gave an incorrectly worded error message when
   the other side did not support the capability.

 * "git fetch" over a remote-helper that cannot respond to "list"
   command could not fetch from a symbolic reference e.g. HEAD.

 * The insn sheet "git rebase -i" creates did not fully honor
   core.abbrev settings.

 * The tests that wanted to see that file becomes unreadable after
   running "chmod a-r file", and the tests that wanted to make sure it
   is not run as root, we used "can we write into the / directory?" as
   a cheap substitute, but on some platforms that is not a good
   heuristics.  The tests and their prerequisites have been updated to
   check what they really require.

 * The configuration variable 'mailinfo.scissors' was hard to
   discover in the documentation.

 * Correct a breakage to git-svn around v2.2 era that triggers
   premature closing of FileHandle.

 * Even though we officially haven't dropped Perl 5.8 support, the
   Getopt::Long package that came with it does not support "--no-"
   prefix to negate a boolean option; manually add support to help
   people with older Getopt::Long package.

Also contains typofixes, documentation updates and trivial code clean-ups.

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

Changes since v2.3.1 are as follows:

Aleksander Boruch-Gruszecki (1):
      merge-file: correctly open files when in a subdir

Aleksey Vasenev (1):
      wincred: fix get credential if username has "@"

Alexander Kuleshov (1):
      Git.pm: two minor typo fixes

Eric Sunshine (1):
      builtin/blame: destroy initialized commit_info only

Jeff King (8):
      t/lib-httpd: switch SANITY check for NOT_ROOT
      t/lib-gpg: include separate public keys in keyring.gpg
      t/lib-gpg: sanity-check that we can actually sign
      config: do not ungetc EOF
      decimal_width: avoid integer overflow
      config_buf_ungetc: warn when pushing back a random character
      for_each_loose_file_in_objdir: take an optional strbuf path
      fast-import: avoid running end_packfile recursively

Jonathon Mah (1):
      sha1_file: fix iterating loose alternate objects

Junio C Hamano (7):
      tests: correct misuses of POSIXPERM
      config.txt: clarify that add.ignore-errors is deprecated
      config.txt: mark deprecated variables more prominently
      Documentation/git-remote.txt: stress that set-url is not for triangular
      CodingGuidelines: describe naming rules for configuration variables
      Prepare for 2.3.2
      Git 2.3.2

Kirill A. Shutemov (1):
      rebase -i: use full object name internally throughout the script

Kyle J. McKay (3):
      git-compat-util: do not step on MAC_OS_X_VERSION_MIN_REQUIRED
      git-send-email.perl: support no- prefix with older GetOptions
      Git::SVN::*: avoid premature FileHandle closure

Matthieu Moy (2):
      Documentation/config.txt: document mailinfo.scissors
      Documentation/git-am.txt: mention mailinfo.scissors config variable

Mike Hommey (2):
      transport-helper: do not request symbolic refs to remote helpers
      transport-helper: fix typo in error message when --signed is not supported

Patrick Steinhardt (1):
      git-submodule.sh: fix '/././' path normalization

Ramsay Allan Jones (1):
      git-compat-util.h: remove redundant code

René Scharfe (4):
      connect: use strcmp() for string comparison
      for-each-ref: use skip_prefix() to avoid duplicate string comparison
      pretty: use starts_with() to check for a prefix
      sha1_name: use strlcpy() to copy strings

Ryuichi Kokubo (1):
      git-svn: fix localtime=true on non-glibc environments

Stefan Beller (2):
      hex.c: reduce memory footprint of sha1_to_hex static buffers
      read-cache.c: free cache entry when refreshing fails

Tom G. Christensen (2):
      Makefile: handle broken curl version number in version check
      ewah: fix building with gcc < 3.4.0

Torsten Bögershausen (1):
      test-lib.sh: set prerequisite SANITY by testing what we really need

Дилян Палаузов (1):
      do not include the same header twice

^ permalink raw reply	[relevance 3%]

* [ANNOUNCE] Git v2.4.0-rc1
@ 2015-04-02 22:08  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-04-02 22:08 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate Git v2.4.0-rc1 is now available for testing at
the usual places.  The changes since the early preview 2.4.0-rc0 is
minimum.  Please give it a good testing.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/testing/

The following public repositories all have a copy of the 'v2.4.0-rc1'
tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 2.4 Release Notes (draft)
=============================

Backward compatibility warning(s)
---------------------------------

This release has a few changes in the user-visible output from
Porcelain commands. These are not meant to be parsed by scripts, but
the users still may want to be aware of the changes:

 * Output from "git log --decorate" (and "%d" format specifier used in
   the userformat "--format=<string>" parameter "git log" family of
   command takes) used to list "HEAD" just like other tips of branch
   names, separated with a comma in between.  E.g.

     $ git log --decorate -1 master
     commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD, master)
     ...

   This release updates the output slightly when HEAD refers to the tip
   of a branch whose name is also shown in the output.  The above is
   shown as:

     $ git log --decorate -1 master
     commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD -> master)
     ...

 * The phrasing "git branch" uses to describe a detached HEAD has been
   updated to match that of "git status":

    - When the HEAD is at the same commit as it was originally
      detached, they now both show "detached at <commit object name>".

    - When the HEAD has moved since it was originally detached,
      they now both show "detached from <commit object name>".

    Earlier "git branch" always used "from"


Updates since v2.3
------------------

Ports

 * Our default I/O size (8 MiB) for large files was too large for some
   platforms with smaller SSIZE_MAX, leading to read(2)/write(2)
   failures.

 * We did not check the curl library version before using
   CURLOPT_PROXYAUTH feature that may not exist.

 * We now detect number of CPUs on older BSD-derived systems.

 * Portability fixes and workarounds for shell scripts have been added
   to help BSD-derived systems.


UI, Workflows & Features

 * The command usage info strings given by "git cmd -h" and in
   documentation have been tweaked for consistency.

 * The "sync" subcommand of "git p4" now allows users to exclude
   subdirectories like its "clone" subcommand does.

 * "git log --invert-grep --grep=WIP" will show only commits that do
   not have the string "WIP" in their messages.

 * "git push" has been taught a "--atomic" option that makes push to
   update more than one ref an "all-or-none" affair.

 * Extending the "push to deploy" added in 2.3, the behaviour of "git
   push" when updating the branch that is checked out can now be
   tweaked by push-to-checkout hook.

 * Using environment variable LANGUAGE and friends on the client side,
   HTTP-based transports now send Accept-Language when making requests.

 * "git send-email" used to accept a mistaken "y" (or "yes") as an
   answer to "What encoding do you want to use [UTF-8]? " without
   questioning.  Now it asks for confirmation when the answer looks
   too short to be a valid encoding name.

 * When "git apply --whitespace=fix" fixed whitespace errors in the
   common context lines, the command reports that it did so.

 * "git status" now allows the "-v" to be given twice to show the
   differences that are left in the working tree not to be committed.

 * "git cherry-pick" used to clean-up the log message even when it is
   merely replaying an existing commit.  It now replays the message
   verbatim unless you are editing the message of resulting commits.

 * "git archive" can now be told to set the 'text' attribute in the
   resulting zip archive.

 * Output from "git log --decorate" mentions HEAD when it points at a
   tip of an branch differently from a detached HEAD.

   This is a potentially backward-incompatible change.

 * "git branch" on a detached HEAD always said "(detached from xyz)",
   even when "git status" would report "detached at xyz".  The HEAD is
   actually at xyz and haven't been moved since it was detached in
   such a case, but the user cannot read what the current value of
   HEAD is when "detached from" is used.

 * "git -C '' subcmd" refused to work in the current directory, unlike
   "cd ''" which silently behaves as a no-op.
   (merge 6a536e2 kn/git-cd-to-empty later to maint).

 * The versionsort.prerelease configuration variable can be used to
   specify that v1.0-pre1 comes before v1.0.

 * A new "push.followTags" configuration turns the "--follow-tags"
   option on by default for the "git push" command.

 * "git log --graph --no-walk A B..." is a conflicting request that
   asks nonsense; no-walk tells us show discrete points in the
   history, while graph asks to draw connections between these
   discrete points. Forbid the combination.

 * "git rev-list --bisect --first-parent" does not work (yet) and can
   even cause SEGV; forbid it.  "git log --bisect --first-parent"
   would not be useful until "git bisect --first-parent" materializes,
   so it is also forbidden for now.


Performance, Internal Implementation, Development Support etc.

 * Implementation of N_() macro has been updated slightly to help us
   detect mistakes.

 * Implementation of "reflog expire" has been restructured to fit the
   reflogs better with the recently updated ref API.

 * The transport-helper did not give transport options such as
   verbosity, progress, cloning, etc. to import and export based
   helpers, like it did for fetch and push based helpers, robbing them
   the chance to honor the wish of the end-users better.

 * The tests that wanted to see that file becomes unreadable after
   running "chmod a-r file", and the tests that wanted to make sure it
   is not run as root, we used "can we write into the / directory?" as
   a cheap substitute, but on some platforms that is not a good
   heuristics.  The tests and their prerequisites have been updated to
   check what they really require.
   (merge f400e51 jk/sanity later to maint).

 * Various issues around "reflog expire", e.g. using --updateref when
   expiring a reflog for a symbolic reference, have been corrected
   and/or made saner.

 * The strbuf API was explained between the API documentation and in
   the header file.  Move missing bits to strbuf.h so that programmers
   can check only one place for all necessary information.

 * The error handling functions and conventions are now documented in
   the API manual.

 * Optimize attribute look-up, mostly useful in "git grep" on a
   project that does not use many attributes, by avoiding it when we
   (should) know that the attributes are not defined in the first
   place.

 * Typofix in comments.
   (merge ef2956a ak/git-pm-typofix later to maint).

 * Code clean-up.
   (merge 0b868f0 sb/hex-object-name-is-at-most-41-bytes-long later to maint).
   (merge 5d30851 dp/remove-duplicated-header-inclusion later to maint).

 * Simplify the ref transaction API around how "the ref should be
   pointing at this object" is specified.

 * Code in "git daemon" to parse out and hold hostnames used in
   request interpolation has been simplified.

 * "git push" codepath has been restructured to make it easier to add
   new configuration bits.

 * The run-command interface was easy to abuse and make a pipe for us
   to read from the process, wait for the process to finish and then
   attempt to read its output, which is a pattern that lead to a
   deadlock.  Fix such uses by introducing a helper to do this
   correctly (i.e. we need to read first and then wait the process to
   finish) and also add code to prevent such abuse in the run-command
   helper.

 * People often forget to chain the commands in their test together
   with &&, leaving a failure from an earlier command in the test go
   unnoticed.  The new GIT_TEST_CHAIN_LINT mechanism allows you to
   catch such a mistake more easily.


Also contains various documentation updates and code clean-ups.


Fixes since v2.3
----------------

Unless otherwise noted, all the fixes since v2.3 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * "git blame HEAD -- missing" failed to correctly say "HEAD" when it
   tried to say "No such path 'missing' in HEAD".
   (merge a46442f jk/blame-commit-label later to maint).

 * "git rerere" (invoked internally from many mergy operations) did
   not correctly signal errors when told to update the working tree
   files and failed to do so for whatever reason.
   (merge 89ea903 jn/rerere-fail-on-auto-update-failure later to maint).

 * Setting diff.submodule to 'log' made "git format-patch" produce
   broken patches.
   (merge 339de50 dk/format-patch-ignore-diff-submodule later to maint).

 * After attempting and failing a password-less authentication
   (e.g. Kerberos), libcURL refuses to fall back to password based
   Basic authentication without a bit of help/encouragement.
   (merge 4dbe664 bc/http-fallback-to-password-after-krb-fails later to maint).

 * The "git push" documentation made the "--repo=<there>" option
   easily misunderstood.
   (merge 57b92a7 mg/push-repo-option-doc later to maint).

 * Code to read branch name from various files in .git/ directory
   would have misbehaved if the code to write them left an empty file.
   (merge 66ec904 jk/status-read-branch-name-fix later to maint).

 * A misspelled conditional that is always true has been fixed.
   (merge 94ee8e2 jk/remote-curl-an-array-in-struct-cannot-be-null later to maint).

 * The documentation incorrectly said that C(opy) and R(ename) are the
   only ones that can be followed by the score number in the output in
   the --raw format.
   (merge ac1c2d9 jc/diff-format-doc later to maint).

 * A broken pack .idx file in the receiving repository prevented the
   dumb http transport from fetching a good copy of it from the other
   side.
   (merge 8b9c2dd jk/dumb-http-idx-fetch-fix later to maint).

 * The error message from "git commit", when a non-existing author
   name was given as value to the "--author=" parameter, has been
   reworded to avoid misunderstanding.
   (merge 1044b1f mg/commit-author-no-match-malformed-message later to maint).

 * "git log --help" used to show rev-list options that are irrelevant
   to the "log" command.
   (merge 3cab02d jc/doc-log-rev-list-options later to maint).

 * "git apply --whitespace=fix" used to under-allocate the memory when
   the fix resulted in a longer text than the original patch.
   (merge 407a792 jc/apply-ws-fix-expands later to maint).

 * The interactive "show a list and let the user choose from it"
   interface "add -i" used showed and prompted to the user even when
   the candidate list was empty, against which the only "choice" the
   user could have made was to choose nothing.
   (merge a9c4641 ak/add-i-empty-candidates later to maint).

 * The insn sheet "git rebase -i" creates did not fully honor
   core.abbrev settings.
   (merge edb72d5 ks/rebase-i-abbrev later to maint).

 * "git fetch" over a remote-helper that cannot respond to "list"
   command could not fetch from a symbolic reference e.g. HEAD.
   (merge 33cae54 mh/deref-symref-over-helper-transport later to maint).

 * "git push --signed" gave an incorrectly worded error message when
   the other side did not support the capability.
   (merge 45917f0 jc/push-cert later to maint).

 * We didn't format an integer that wouldn't fit in "int" but in
   "uintmax_t" correctly.
   (merge d306f3d jk/decimal-width-for-uintmax later to maint).

 * Reading configuration from a blob object, when it ends with a lone
   CR, use to confuse the configuration parser.
   (merge 1d0655c jk/config-no-ungetc-eof later to maint).

 * The pack bitmap support did not build with older versions of GCC.
   (merge bd4e882 jk/pack-bitmap later to maint).

 * The documentation wasn't clear that "remote.<nick>.pushURL" and
   "remote.<nick>.URL" are there to name the same repository accessed
   via different transports, not two separate repositories.
   (merge 697f652 jc/remote-set-url-doc later to maint).

 * Older GnuPG implementations may not correctly import the keyring
   material we prepare for the tests to use.
   (merge 1f985d6 ch/new-gpg-drops-rfc-1991 later to maint).

 * The credential helper for Windows (in contrib/) used to mishandle
   a user name with an at-sign in it.
   (merge 13d261e av/wincred-with-at-in-username-fix later to maint).

 * Longstanding configuration variable naming rules has been added to
   the documentation.
   (merge 35840a3 jc/conf-var-doc later to maint).

 * An earlier workaround to squelch unhelpful deprecation warnings
   from the compiler on Mac OSX unnecessarily set minimum required
   version of the OS, which the user might want to raise (or lower)
   for other reasons.
   (merge 88c03eb es/squelch-openssl-warnings-on-macosx later to maint).

 * Certain older vintages of cURL give irregular output from
   "curl-config --vernum", which confused our build system.
   (merge 3af6792 tc/curl-vernum-output-broken-in-7.11 later to maint).

 * In v2.2.0, we broke "git prune" that runs in a repository that
   borrows from an alternate object store.
   (merge b0a4264 jk/prune-mtime later to maint).

 * "git submodule add" failed to squash "path/to/././submodule" to
   "path/to/submodule".
   (merge 8196e72 ps/submodule-sanitize-path-upon-add later to maint).

 * "git merge-file" did not work correctly in a subdirectory.
   (merge 204a8ff ab/merge-file-prefix later to maint).

 * "git blame" died, trying to free an uninitialized piece of memory.
   (merge e600592 es/blame-commit-info-fix later to maint).

 * "git fast-import" used to crash when it could not close and
   conclude the resulting packfile cleanly.
   (merge 5e915f3 jk/fast-import-die-nicely-fix later to maint).

 * "update-index --refresh" used to leak when an entry cannot be
   refreshed for whatever reason.
   (merge bc1c2ca sb/plug-leak-in-make-cache-entry later to maint).

 * The "interpolated-path" option of "git daemon" inserted any string
   client declared on the "host=" capability request without checking.
   Sanitize and limit %H and %CH to a saner and a valid DNS name.
   (merge b485373 jk/daemon-interpolate later to maint).

 * "git daemon" looked up the hostname even when "%CH" and "%IP"
   interpolations are not requested, which was unnecessary.
   (merge dc8edc8 rs/daemon-interpolate later to maint).

 * Even though we officially haven't dropped Perl 5.8 support, the
   Getopt::Long package that came with it does not support "--no-"
   prefix to negate a boolean option; manually add support to help
   people with older Getopt::Long package.
   (merge f471494 km/send-email-getopt-long-workarounds later to maint).

 * "git apply" was not very careful about reading from, removing,
   updating and creating paths outside the working tree (under
   --index/--cached) or the current directory (when used as a
   replacement for GNU patch).
   (merge e0d201b jc/apply-beyond-symlink later to maint).

 * A breakage to git-svn around v2.2 era that triggers premature
   closing of FileHandle has been corrected.
   (merge e426311 ew/svn-maint-fixes later to maint).

 * We did not parse username followed by literal IPv6 address in SSH
   transport URLs, e.g. ssh://user@[2001:db8::1]:22/repo.git
   correctly.
   (merge 3f55cca tb/connect-ipv6-parse-fix later to maint).

 * The configuration variable 'mailinfo.scissors' was hard to
   discover in the documentation.
   (merge afb5de7 mm/am-c-doc later to maint).

 * The interaction between "git submodule update" and the
   submodule.*.update configuration was not clearly documented.
   (merge 5c31acf ms/submodule-update-config-doc later to maint).

 * "git diff --shortstat --dirstat=changes" showed a dirstat based on
   lines that was never asked by the end user in addition to the
   dirstat that the user asked for.
   (merge ab27389 mk/diff-shortstat-dirstat-fix later to maint).

 * "git remote add" mentioned "--tags" and "--no-tags" and was not
   clear that fetch from the remote in the future will use the default
   behaviour when neither is given to override it.
   (merge aaba0ab mg/doc-remote-tags-or-not later to maint).

 * Description given by "grep -h" for its --exclude-standard option
   was phrased poorly.
   (merge 77fdb8a nd/grep-exclude-standard-help-fix later to maint).

 * "git rebase -i" recently started to include the number of
   commits in the insn sheet to be processed, but on a platform
   that prepends leading whitespaces to "wc -l" output, the numbers
   are shown with extra whitespaces that aren't necessary.
   (merge 2185d3b es/rebase-i-count-todo later to maint).

 * The borrowed code in kwset API did not follow our usual convention
   to use "unsigned char" to store values that range from 0-255.
   (merge 189c860 bw/kwset-use-unsigned later to maint).

 * A corrupt input to "git diff -M" used to cause it to segfault.
   (merge 4d6be03 jk/diffcore-rename-duplicate later to maint).

 * Certain builds of GPG triggered false breakages in a test.
   (merge 3f88c1b mg/verify-commit later to maint).

 * "git imap-send" learned to optionally talk with an IMAP server via
   libcURL; because there is no other option when Git is built with
   NO_OPENSSL option, use that codepath by default under such
   configuration.
   (merge dcd01ea km/imap-send-libcurl-options later to maint).

 * "git log --decorate" did not reset colors correctly around the
   branch names.
   (merge 5ee8758 jc/decorate-leaky-separator-color later to maint).

 * The code that reads from the ctags file in the completion script
   (in contrib/) did not spell ${param/pattern/string} substitution
   correctly, which happened to work with bash but not with zsh.
   (merge db8d750 js/completion-ctags-pattern-substitution-fix later to maint).

 * The transfer.hiderefs support did not quite work for smart-http
   transport.
   (merge 8ddf3ca jk/smart-http-hide-refs later to maint).

 * "git tag -h" used to show the "--column" and "--sort" options
   that are about listing in a wrong section.
   (merge dd059c6 jk/tag-h-column-is-a-listing-option later to maint).

 * "git prune" used to largely ignore broken refs when deciding which
   objects are still being used, which could spread an existing small
   damage and make it a larger one.
   (merge ea56c4e jk/prune-with-corrupt-refs later to maint).

 * The split-index mode introduced at v2.3.0-rc0~41 was broken in the
   codepath to protect us against a broken reimplementation of Git
   that writes an invalid index with duplicated index entries, etc.
   (merge 03f15a7 tg/fix-check-order-with-split-index later to maint).

 * "git fetch" that fetches a commit using the allow-tip-sha1-in-want
   extension could have failed to fetch all the requested refs.
   (merge 32d0462 jk/fetch-pack later to maint).

 * An failure early in the "git clone" that started creating the
   working tree and repository could have resulted in some directories
   and files left without getting cleaned up.
   (merge 16eff6c jk/cleanup-failed-clone later to maint).

 * Recommend format-patch and send-email for those who want to submit
   patches to this project.
   (merge b25c469 jc/submitting-patches-mention-send-email later to maint).

 * Even though "git grep --quiet" is run merely to ask for the exit
   status, we spawned the pager regardless.  Stop doing that.
   (merge c2048f0 ws/grep-quiet-no-pager later to maint).

 * The prompt script (in contrib/) did not show the untracked sign
   when working in a subdirectory without any untracked files.
   (merge 9bdc517 ct/prompt-untracked-fix later to maint).

 * Code cleanups and documentation updates.
   (merge 2ce63e9 rs/simple-cleanups later to maint).
   (merge 33baa69 rj/no-xopen-source-for-cygwin later to maint).
   (merge 817d03e jc/diff-test-updates later to maint).
   (merge eb32c66 ak/t5516-typofix later to maint).
   (merge bcd57cb mr/doc-clean-f-f later to maint).
   (merge 0d6accc mg/doc-status-color-slot later to maint).
   (merge 53e53c7 sg/completion-remote later to maint).
   (merge 8fa7975 ak/git-done-help-cleanup later to maint).
   (merge 9a6f128 rs/deflate-init-cleanup later to maint).
   (merge 6f75d45 rs/use-isxdigit later to maint).
   (merge 376e4b3 jk/test-annoyances later to maint).
   (merge 7032054 nd/doc-git-index-version later to maint).
   (merge e869c5e tg/test-index-v4 later to maint).
   (merge 599d223 jk/simplify-csum-file-sha1fd-check later to maint).
   (merge 260d585 sg/completion-gitcomp-nl-for-refs later to maint).
   (merge 777c55a jc/report-path-error-to-dir later to maint).
   (merge fddfaf8 ph/push-doc-cas later to maint).
   (merge 129260c ss/pull-rebase-preserve later to maint).

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

Changes since v2.4.0-rc0 are as follows:

Junio C Hamano (6):
      add_to_index(): free unused cache-entry
      Update mailmap to spell out "Alexander Kuleshov"
      Prepare for 2.3.5
      RelNotes: minor doc updates
      Git 2.3.5
      Git 2.4.0-rc1

Phil Hord (1):
      git-push.txt: clean up force-with-lease wording

Ralf Thielow (1):
      send-pack: unify error messages for unsupported capabilities

Sebastian Schuberth (2):
      docs: clarify "preserve" option wording for git-pull
      docs: clarify what git-rebase's "-p" / "--preserve-merges" does

Stefan Beller (9):
      read-cache: free cache entry in add_to_index in case of early return
      update-index: fix a memleak
      builtin/apply.c: fix a memleak
      merge-blobs.c: fix a memleak
      merge-recursive: fix memleaks
      http-push: remove unneeded cleanup
      commit.c: fix a memory leak
      read-cache: fix memleak
      http: release the memory of a http pack request as well

Thomas Ackermann (2):
      api-error-handling doc: typofix
      2.3.2 release notes: typofix

^ permalink raw reply	[relevance 2%]

* [ANNOUNCE] Git v2.4.0-rc2
@ 2015-04-14 21:48  2% Junio C Hamano
  2015-04-16  2:05  3% ` Bryan Turner
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-04-14 21:48 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate Git v2.4.0-rc2 is now available for testing at
the usual places.  The difference since -rc1 is mostly l10n and a
handful of documentation clean-ups.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/testing/

The following public repositories all have a copy of the 'v2.4.0-rc2'
tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 2.4 Release Notes (draft)
=============================

Backward compatibility warning(s)
---------------------------------

This release has a few changes in the user-visible output from
Porcelain commands. These are not meant to be parsed by scripts, but
the users still may want to be aware of the changes:

 * Output from "git log --decorate" (and "%d" format specifier used in
   the userformat "--format=<string>" parameter "git log" family of
   command takes) used to list "HEAD" just like other tips of branch
   names, separated with a comma in between.  E.g.

     $ git log --decorate -1 master
     commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD, master)
     ...

   This release updates the output slightly when HEAD refers to the tip
   of a branch whose name is also shown in the output.  The above is
   shown as:

     $ git log --decorate -1 master
     commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD -> master)
     ...

 * The phrasing "git branch" uses to describe a detached HEAD has been
   updated to match that of "git status":

    - When the HEAD is at the same commit as it was originally
      detached, they now both show "detached at <commit object name>".

    - When the HEAD has moved since it was originally detached,
      they now both show "detached from <commit object name>".

    Earlier "git branch" always used "from"


Updates since v2.3
------------------

Ports

 * Our default I/O size (8 MiB) for large files was too large for some
   platforms with smaller SSIZE_MAX, leading to read(2)/write(2)
   failures.

 * We did not check the curl library version before using
   CURLOPT_PROXYAUTH feature that may not exist.

 * We now detect number of CPUs on older BSD-derived systems.

 * Portability fixes and workarounds for shell scripts have been added
   to help BSD-derived systems.


UI, Workflows & Features

 * The command usage info strings given by "git cmd -h" and in
   documentation have been tweaked for consistency.

 * The "sync" subcommand of "git p4" now allows users to exclude
   subdirectories like its "clone" subcommand does.

 * "git log --invert-grep --grep=WIP" will show only commits that do
   not have the string "WIP" in their messages.

 * "git push" has been taught a "--atomic" option that makes push to
   update more than one ref an "all-or-none" affair.

 * Extending the "push to deploy" added in 2.3, the behaviour of "git
   push" when updating the branch that is checked out can now be
   tweaked by push-to-checkout hook.

 * Using environment variable LANGUAGE and friends on the client side,
   HTTP-based transports now send Accept-Language when making requests.

 * "git send-email" used to accept a mistaken "y" (or "yes") as an
   answer to "What encoding do you want to use [UTF-8]? " without
   questioning.  Now it asks for confirmation when the answer looks
   too short to be a valid encoding name.

 * When "git apply --whitespace=fix" fixed whitespace errors in the
   common context lines, the command reports that it did so.

 * "git status" now allows the "-v" to be given twice to show the
   differences that are left in the working tree not to be committed.

 * "git cherry-pick" used to clean-up the log message even when it is
   merely replaying an existing commit.  It now replays the message
   verbatim unless you are editing the message of resulting commits.

 * "git archive" can now be told to set the 'text' attribute in the
   resulting zip archive.

 * Output from "git log --decorate" mentions HEAD when it points at a
   tip of an branch differently from a detached HEAD.

   This is a potentially backward-incompatible change.

 * "git branch" on a detached HEAD always said "(detached from xyz)",
   even when "git status" would report "detached at xyz".  The HEAD is
   actually at xyz and haven't been moved since it was detached in
   such a case, but the user cannot read what the current value of
   HEAD is when "detached from" is used.

 * "git -C '' subcmd" refused to work in the current directory, unlike
   "cd ''" which silently behaves as a no-op.
   (merge 6a536e2 kn/git-cd-to-empty later to maint).

 * The versionsort.prerelease configuration variable can be used to
   specify that v1.0-pre1 comes before v1.0.

 * A new "push.followTags" configuration turns the "--follow-tags"
   option on by default for the "git push" command.

 * "git log --graph --no-walk A B..." is a conflicting request that
   asks nonsense; no-walk tells us show discrete points in the
   history, while graph asks to draw connections between these
   discrete points. Forbid the combination.

 * "git rev-list --bisect --first-parent" does not work (yet) and can
   even cause SEGV; forbid it.  "git log --bisect --first-parent"
   would not be useful until "git bisect --first-parent" materializes,
   so it is also forbidden for now.


Performance, Internal Implementation, Development Support etc.

 * Implementation of N_() macro has been updated slightly to help us
   detect mistakes.

 * Implementation of "reflog expire" has been restructured to fit the
   reflogs better with the recently updated ref API.

 * The transport-helper did not give transport options such as
   verbosity, progress, cloning, etc. to import and export based
   helpers, like it did for fetch and push based helpers, robbing them
   the chance to honor the wish of the end-users better.

 * The tests that wanted to see that file becomes unreadable after
   running "chmod a-r file", and the tests that wanted to make sure it
   is not run as root, we used "can we write into the / directory?" as
   a cheap substitute, but on some platforms that is not a good
   heuristics.  The tests and their prerequisites have been updated to
   check what they really require.
   (merge f400e51 jk/sanity later to maint).

 * Various issues around "reflog expire", e.g. using --updateref when
   expiring a reflog for a symbolic reference, have been corrected
   and/or made saner.

 * The strbuf API was explained between the API documentation and in
   the header file.  Move missing bits to strbuf.h so that programmers
   can check only one place for all necessary information.

 * The error handling functions and conventions are now documented in
   the API manual.

 * Optimize attribute look-up, mostly useful in "git grep" on a
   project that does not use many attributes, by avoiding it when we
   (should) know that the attributes are not defined in the first
   place.

 * Typofix in comments.
   (merge ef2956a ak/git-pm-typofix later to maint).

 * Code clean-up.
   (merge 0b868f0 sb/hex-object-name-is-at-most-41-bytes-long later to maint).
   (merge 5d30851 dp/remove-duplicated-header-inclusion later to maint).

 * Simplify the ref transaction API around how "the ref should be
   pointing at this object" is specified.

 * Code in "git daemon" to parse out and hold hostnames used in
   request interpolation has been simplified.

 * "git push" codepath has been restructured to make it easier to add
   new configuration bits.

 * The run-command interface was easy to abuse and make a pipe for us
   to read from the process, wait for the process to finish and then
   attempt to read its output, which is a pattern that lead to a
   deadlock.  Fix such uses by introducing a helper to do this
   correctly (i.e. we need to read first and then wait the process to
   finish) and also add code to prevent such abuse in the run-command
   helper.

 * People often forget to chain the commands in their test together
   with &&, leaving a failure from an earlier command in the test go
   unnoticed.  The new GIT_TEST_CHAIN_LINT mechanism allows you to
   catch such a mistake more easily.


Also contains various documentation updates and code clean-ups.


Fixes since v2.3
----------------

Unless otherwise noted, all the fixes since v2.3 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * "git blame HEAD -- missing" failed to correctly say "HEAD" when it
   tried to say "No such path 'missing' in HEAD".
   (merge a46442f jk/blame-commit-label later to maint).

 * "git rerere" (invoked internally from many mergy operations) did
   not correctly signal errors when told to update the working tree
   files and failed to do so for whatever reason.
   (merge 89ea903 jn/rerere-fail-on-auto-update-failure later to maint).

 * Setting diff.submodule to 'log' made "git format-patch" produce
   broken patches.
   (merge 339de50 dk/format-patch-ignore-diff-submodule later to maint).

 * After attempting and failing a password-less authentication
   (e.g. Kerberos), libcURL refuses to fall back to password based
   Basic authentication without a bit of help/encouragement.
   (merge 4dbe664 bc/http-fallback-to-password-after-krb-fails later to maint).

 * The "git push" documentation made the "--repo=<there>" option
   easily misunderstood.
   (merge 57b92a7 mg/push-repo-option-doc later to maint).

 * Code to read branch name from various files in .git/ directory
   would have misbehaved if the code to write them left an empty file.
   (merge 66ec904 jk/status-read-branch-name-fix later to maint).

 * A misspelled conditional that is always true has been fixed.
   (merge 94ee8e2 jk/remote-curl-an-array-in-struct-cannot-be-null later to maint).

 * The documentation incorrectly said that C(opy) and R(ename) are the
   only ones that can be followed by the score number in the output in
   the --raw format.
   (merge ac1c2d9 jc/diff-format-doc later to maint).

 * A broken pack .idx file in the receiving repository prevented the
   dumb http transport from fetching a good copy of it from the other
   side.
   (merge 8b9c2dd jk/dumb-http-idx-fetch-fix later to maint).

 * The error message from "git commit", when a non-existing author
   name was given as value to the "--author=" parameter, has been
   reworded to avoid misunderstanding.
   (merge 1044b1f mg/commit-author-no-match-malformed-message later to maint).

 * "git log --help" used to show rev-list options that are irrelevant
   to the "log" command.
   (merge 3cab02d jc/doc-log-rev-list-options later to maint).

 * "git apply --whitespace=fix" used to under-allocate the memory when
   the fix resulted in a longer text than the original patch.
   (merge 407a792 jc/apply-ws-fix-expands later to maint).

 * The interactive "show a list and let the user choose from it"
   interface "add -i" used showed and prompted to the user even when
   the candidate list was empty, against which the only "choice" the
   user could have made was to choose nothing.
   (merge a9c4641 ak/add-i-empty-candidates later to maint).

 * The insn sheet "git rebase -i" creates did not fully honor
   core.abbrev settings.
   (merge edb72d5 ks/rebase-i-abbrev later to maint).

 * "git fetch" over a remote-helper that cannot respond to "list"
   command could not fetch from a symbolic reference e.g. HEAD.
   (merge 33cae54 mh/deref-symref-over-helper-transport later to maint).

 * "git push --signed" gave an incorrectly worded error message when
   the other side did not support the capability.
   (merge 45917f0 jc/push-cert later to maint).

 * We didn't format an integer that wouldn't fit in "int" but in
   "uintmax_t" correctly.
   (merge d306f3d jk/decimal-width-for-uintmax later to maint).

 * Reading configuration from a blob object, when it ends with a lone
   CR, use to confuse the configuration parser.
   (merge 1d0655c jk/config-no-ungetc-eof later to maint).

 * The pack bitmap support did not build with older versions of GCC.
   (merge bd4e882 jk/pack-bitmap later to maint).

 * The documentation wasn't clear that "remote.<nick>.pushURL" and
   "remote.<nick>.URL" are there to name the same repository accessed
   via different transports, not two separate repositories.
   (merge 697f652 jc/remote-set-url-doc later to maint).

 * Older GnuPG implementations may not correctly import the keyring
   material we prepare for the tests to use.
   (merge 1f985d6 ch/new-gpg-drops-rfc-1991 later to maint).

 * The credential helper for Windows (in contrib/) used to mishandle
   a user name with an at-sign in it.
   (merge 13d261e av/wincred-with-at-in-username-fix later to maint).

 * "diff-highlight" (in contrib/) used to show byte-by-byte
   differences, which meant that multi-byte characters can be chopped
   in the middle.  It learned to pay attention to character boundaries
   (assuming the UTF-8 payload).
   (merge 8d00662 jk/colors later to maint).

 * "git merge --quiet" did not squelch messages from the underlying
   merge-recursive strategy.
   (merge 2bf15a3 jk/merge-quiet later to maint).

 * Longstanding configuration variable naming rules has been added to
   the documentation.
   (merge 35840a3 jc/conf-var-doc later to maint).

 * An earlier workaround to squelch unhelpful deprecation warnings
   from the compiler on Mac OSX unnecessarily set minimum required
   version of the OS, which the user might want to raise (or lower)
   for other reasons.
   (merge 88c03eb es/squelch-openssl-warnings-on-macosx later to maint).

 * Certain older vintages of cURL give irregular output from
   "curl-config --vernum", which confused our build system.
   (merge 3af6792 tc/curl-vernum-output-broken-in-7.11 later to maint).

 * In v2.2.0, we broke "git prune" that runs in a repository that
   borrows from an alternate object store.
   (merge b0a4264 jk/prune-mtime later to maint).

 * "git submodule add" failed to squash "path/to/././submodule" to
   "path/to/submodule".
   (merge 8196e72 ps/submodule-sanitize-path-upon-add later to maint).

 * "git merge-file" did not work correctly in a subdirectory.
   (merge 204a8ff ab/merge-file-prefix later to maint).

 * "git blame" died, trying to free an uninitialized piece of memory.
   (merge e600592 es/blame-commit-info-fix later to maint).

 * "git fast-import" used to crash when it could not close and
   conclude the resulting packfile cleanly.
   (merge 5e915f3 jk/fast-import-die-nicely-fix later to maint).

 * "update-index --refresh" used to leak when an entry cannot be
   refreshed for whatever reason.
   (merge bc1c2ca sb/plug-leak-in-make-cache-entry later to maint).

 * The "interpolated-path" option of "git daemon" inserted any string
   client declared on the "host=" capability request without checking.
   Sanitize and limit %H and %CH to a saner and a valid DNS name.
   (merge b485373 jk/daemon-interpolate later to maint).

 * "git daemon" looked up the hostname even when "%CH" and "%IP"
   interpolations are not requested, which was unnecessary.
   (merge dc8edc8 rs/daemon-interpolate later to maint).

 * Even though we officially haven't dropped Perl 5.8 support, the
   Getopt::Long package that came with it does not support "--no-"
   prefix to negate a boolean option; manually add support to help
   people with older Getopt::Long package.
   (merge f471494 km/send-email-getopt-long-workarounds later to maint).

 * "git apply" was not very careful about reading from, removing,
   updating and creating paths outside the working tree (under
   --index/--cached) or the current directory (when used as a
   replacement for GNU patch).
   (merge e0d201b jc/apply-beyond-symlink later to maint).

 * A breakage to git-svn around v2.2 era that triggers premature
   closing of FileHandle has been corrected.
   (merge e426311 ew/svn-maint-fixes later to maint).

 * We did not parse username followed by literal IPv6 address in SSH
   transport URLs, e.g. ssh://user@[2001:db8::1]:22/repo.git
   correctly.
   (merge 6b6c5f7 tb/connect-ipv6-parse-fix later to maint).

 * The configuration variable 'mailinfo.scissors' was hard to
   discover in the documentation.
   (merge afb5de7 mm/am-c-doc later to maint).

 * The interaction between "git submodule update" and the
   submodule.*.update configuration was not clearly documented.
   (merge 5c31acf ms/submodule-update-config-doc later to maint).

 * "git diff --shortstat --dirstat=changes" showed a dirstat based on
   lines that was never asked by the end user in addition to the
   dirstat that the user asked for.
   (merge ab27389 mk/diff-shortstat-dirstat-fix later to maint).

 * "git remote add" mentioned "--tags" and "--no-tags" and was not
   clear that fetch from the remote in the future will use the default
   behaviour when neither is given to override it.
   (merge aaba0ab mg/doc-remote-tags-or-not later to maint).

 * Description given by "grep -h" for its --exclude-standard option
   was phrased poorly.
   (merge 77fdb8a nd/grep-exclude-standard-help-fix later to maint).

 * "git rebase -i" recently started to include the number of
   commits in the insn sheet to be processed, but on a platform
   that prepends leading whitespaces to "wc -l" output, the numbers
   are shown with extra whitespaces that aren't necessary.
   (merge 2185d3b es/rebase-i-count-todo later to maint).

 * The borrowed code in kwset API did not follow our usual convention
   to use "unsigned char" to store values that range from 0-255.
   (merge 189c860 bw/kwset-use-unsigned later to maint).

 * A corrupt input to "git diff -M" used to cause it to segfault.
   (merge 4d6be03 jk/diffcore-rename-duplicate later to maint).

 * Certain builds of GPG triggered false breakages in a test.
   (merge 3f88c1b mg/verify-commit later to maint).

 * "git imap-send" learned to optionally talk with an IMAP server via
   libcURL; because there is no other option when Git is built with
   NO_OPENSSL option, use that codepath by default under such
   configuration.
   (merge dcd01ea km/imap-send-libcurl-options later to maint).

 * "git log --decorate" did not reset colors correctly around the
   branch names.
   (merge 5ee8758 jc/decorate-leaky-separator-color later to maint).

 * The code that reads from the ctags file in the completion script
   (in contrib/) did not spell ${param/pattern/string} substitution
   correctly, which happened to work with bash but not with zsh.
   (merge db8d750 js/completion-ctags-pattern-substitution-fix later to maint).

 * The transfer.hiderefs support did not quite work for smart-http
   transport.
   (merge 8ddf3ca jk/smart-http-hide-refs later to maint).

 * "git tag -h" used to show the "--column" and "--sort" options
   that are about listing in a wrong section.
   (merge dd059c6 jk/tag-h-column-is-a-listing-option later to maint).

 * "git prune" used to largely ignore broken refs when deciding which
   objects are still being used, which could spread an existing small
   damage and make it a larger one.
   (merge ea56c4e jk/prune-with-corrupt-refs later to maint).

 * The split-index mode introduced at v2.3.0-rc0~41 was broken in the
   codepath to protect us against a broken reimplementation of Git
   that writes an invalid index with duplicated index entries, etc.
   (merge 03f15a7 tg/fix-check-order-with-split-index later to maint).

 * "git fetch" that fetches a commit using the allow-tip-sha1-in-want
   extension could have failed to fetch all the requested refs.
   (merge 32d0462 jk/fetch-pack later to maint).

 * An failure early in the "git clone" that started creating the
   working tree and repository could have resulted in some directories
   and files left without getting cleaned up.
   (merge 16eff6c jk/cleanup-failed-clone later to maint).

 * Recommend format-patch and send-email for those who want to submit
   patches to this project.
   (merge b25c469 jc/submitting-patches-mention-send-email later to maint).

 * Even though "git grep --quiet" is run merely to ask for the exit
   status, we spawned the pager regardless.  Stop doing that.
   (merge c2048f0 ws/grep-quiet-no-pager later to maint).

 * The prompt script (in contrib/) did not show the untracked sign
   when working in a subdirectory without any untracked files.
   (merge 9bdc517 ct/prompt-untracked-fix later to maint).

 * Code cleanups and documentation updates.
   (merge 2ce63e9 rs/simple-cleanups later to maint).
   (merge 33baa69 rj/no-xopen-source-for-cygwin later to maint).
   (merge 817d03e jc/diff-test-updates later to maint).
   (merge eb32c66 ak/t5516-typofix later to maint).
   (merge bcd57cb mr/doc-clean-f-f later to maint).
   (merge 0d6accc mg/doc-status-color-slot later to maint).
   (merge 53e53c7 sg/completion-remote later to maint).
   (merge 8fa7975 ak/git-done-help-cleanup later to maint).
   (merge 9a6f128 rs/deflate-init-cleanup later to maint).
   (merge 6f75d45 rs/use-isxdigit later to maint).
   (merge 376e4b3 jk/test-annoyances later to maint).
   (merge 7032054 nd/doc-git-index-version later to maint).
   (merge e869c5e tg/test-index-v4 later to maint).
   (merge 599d223 jk/simplify-csum-file-sha1fd-check later to maint).
   (merge 260d585 sg/completion-gitcomp-nl-for-refs later to maint).
   (merge 777c55a jc/report-path-error-to-dir later to maint).
   (merge fddfaf8 ph/push-doc-cas later to maint).
   (merge d50d31e ss/pull-rebase-preserve later to maint).
   (merge c8c3f1d pt/enter-repo-comment-fix later to maint).
   (merge d7bfb9e jz/gitweb-conf-doc-fix later to maint).
   (merge f907282 jk/cherry-pick-docfix later to maint).
   (merge d3c0811 iu/fix-parse-options-h-comment later to maint).
   (merge 6c3b2af jg/cguide-we-cannot-count later to maint).
   (merge 2b8bd44 jk/pack-corruption-post-mortem later to maint).
   (merge 9585cb8 jn/doc-fast-import-no-16-octopus-limit later to maint).

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

Changes since v2.4.0-rc1 are as follows:

Alex Henrie (2):
      l10n: ca.po: update translation
      l10n: ca.po: update translation

Alexander Shopov (1):
      l10n: Updated Bulgarian translation of git (2305t,0f,0u)

Dimitriy Ryazantcev (3):
      l10n: ru: added Russian translation
      l10n: ru: updated Russian translation
      l10n: ru: updated Russian translation

Ivan Ukhov (1):
      parse-options.h: OPTION_{BIT,SET_INT} do not store pointer to defval

Jean-Noel Avila (2):
      l10n: fr.po v2.4.0-rc0 round 1
      l10n: fr.po v2.4.0 round 2

Jeff King (3):
      cherry-pick: fix docs describing handling of empty commits
      howto: document more tools for recovery corruption
      merge: pass verbosity flag down to merge-recursive

Jiang Xin (5):
      l10n: git.pot: v2.4.0 round 1 (99 new, 92 removed)
      l10n: zh_CN: translations for git v2.4.0-rc0
      l10n: git.pot: v2.4.0 round 2 (1 update)
      l10n: zh_CN: for git v2.4.0 l10n round 2
      l10n: TEAMS: Change repository URL of zh_CN

John Keeping (1):
      streaming.c: fix a memleak

Jonathan Nieder (1):
      fast-import doc: remove suggested 16-parent limit

Julian Gindi (1):
      CodingGuidelines: update 'rough' rule count

Junio C Hamano (2):
      push-to-deploy: allow pushing into an unborn branch and updating it
      Git 2.4.0-rc2

Jérôme Zago (1):
      gitweb.conf.txt: say "build-time", not "built-time"

Kyle J. McKay (1):
      diff-highlight: do not split multibyte characters

Matthias Rüster (1):
      l10n: de.po: translate 'symbolic link' as 'symbolische Verknüpfung'

Michael J Gruber (1):
      l10n: de.po: fix negation for commit -a with paths

Paul Tan (1):
      enter_repo(): fix docs to match code

Peter Krefting (2):
      l10n: sv.po: Update Swedish translation (2305t0f0u)
      l10n: sv.po: Update Swedish translation (2305t0f0u)

Phillip Sz (1):
      l10n: de.po: add space before ellipsis

Ralf Thielow (3):
      l10n: de.po: fix messages with abbreviated hashs
      l10n: de.po: translate 99 new messages
      l10n: de.po: translate one message

Stefan Beller (1):
      wt-status.c: fix a memleak

Trần Ngọc Quân (2):
      l10n: vi.po: Updated Vietnamese translation
      l10n: vi.po(2305t): Updated 1 new string

^ permalink raw reply	[relevance 2%]

* Re: [ANNOUNCE] Git v2.4.0-rc2
  2015-04-14 21:48  2% [ANNOUNCE] Git v2.4.0-rc2 Junio C Hamano
@ 2015-04-16  2:05  3% ` Bryan Turner
  0 siblings, 0 replies; 200+ results
From: Bryan Turner @ 2015-04-16  2:05 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Users

On Wed, Apr 15, 2015 at 7:48 AM, Junio C Hamano <gitster@pobox.com> wrote:
>
> A release candidate Git v2.4.0-rc2 is now available for testing at
> the usual places.  The difference since -rc1 is mostly l10n and a
> handful of documentation clean-ups.
>
> The tarballs are found at:
>
>     https://www.kernel.org/pub/software/scm/git/testing/
>
> The following public repositories all have a copy of the 'v2.4.0-rc2'
> tag and the 'master' branch that the tag points at:
>
>   url = https://kernel.googlesource.com/pub/scm/git/git
>   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 2.4 Release Notes (draft)
> =============================
>
> Backward compatibility warning(s)
> ---------------------------------
>
> This release has a few changes in the user-visible output from
> Porcelain commands. These are not meant to be parsed by scripts, but
> the users still may want to be aware of the changes:
>
>  * Output from "git log --decorate" (and "%d" format specifier used in
>    the userformat "--format=<string>" parameter "git log" family of
>    command takes) used to list "HEAD" just like other tips of branch
>    names, separated with a comma in between.  E.g.
>
>      $ git log --decorate -1 master
>      commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD, master)
>      ...
>
>    This release updates the output slightly when HEAD refers to the tip
>    of a branch whose name is also shown in the output.  The above is
>    shown as:
>
>      $ git log --decorate -1 master
>      commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD -> master)
>      ...
>
>  * The phrasing "git branch" uses to describe a detached HEAD has been
>    updated to match that of "git status":
>
>     - When the HEAD is at the same commit as it was originally
>       detached, they now both show "detached at <commit object name>".
>
>     - When the HEAD has moved since it was originally detached,
>       they now both show "detached from <commit object name>".
>
>     Earlier "git branch" always used "from"
>
>
> Updates since v2.3
> ------------------
>
> Ports
>
>  * Our default I/O size (8 MiB) for large files was too large for some
>    platforms with smaller SSIZE_MAX, leading to read(2)/write(2)
>    failures.
>
>  * We did not check the curl library version before using
>    CURLOPT_PROXYAUTH feature that may not exist.
>
>  * We now detect number of CPUs on older BSD-derived systems.
>
>  * Portability fixes and workarounds for shell scripts have been added
>    to help BSD-derived systems.
>
>
> UI, Workflows & Features
>
>  * The command usage info strings given by "git cmd -h" and in
>    documentation have been tweaked for consistency.
>
>  * The "sync" subcommand of "git p4" now allows users to exclude
>    subdirectories like its "clone" subcommand does.
>
>  * "git log --invert-grep --grep=WIP" will show only commits that do
>    not have the string "WIP" in their messages.
>
>  * "git push" has been taught a "--atomic" option that makes push to
>    update more than one ref an "all-or-none" affair.
>
>  * Extending the "push to deploy" added in 2.3, the behaviour of "git
>    push" when updating the branch that is checked out can now be
>    tweaked by push-to-checkout hook.
>
>  * Using environment variable LANGUAGE and friends on the client side,
>    HTTP-based transports now send Accept-Language when making requests.
>
>  * "git send-email" used to accept a mistaken "y" (or "yes") as an
>    answer to "What encoding do you want to use [UTF-8]? " without
>    questioning.  Now it asks for confirmation when the answer looks
>    too short to be a valid encoding name.
>
>  * When "git apply --whitespace=fix" fixed whitespace errors in the
>    common context lines, the command reports that it did so.
>
>  * "git status" now allows the "-v" to be given twice to show the
>    differences that are left in the working tree not to be committed.
>
>  * "git cherry-pick" used to clean-up the log message even when it is
>    merely replaying an existing commit.  It now replays the message
>    verbatim unless you are editing the message of resulting commits.
>
>  * "git archive" can now be told to set the 'text' attribute in the
>    resulting zip archive.
>
>  * Output from "git log --decorate" mentions HEAD when it points at a
>    tip of an branch differently from a detached HEAD.
>
>    This is a potentially backward-incompatible change.
>
>  * "git branch" on a detached HEAD always said "(detached from xyz)",
>    even when "git status" would report "detached at xyz".  The HEAD is
>    actually at xyz and haven't been moved since it was detached in
>    such a case, but the user cannot read what the current value of
>    HEAD is when "detached from" is used.
>
>  * "git -C '' subcmd" refused to work in the current directory, unlike
>    "cd ''" which silently behaves as a no-op.
>    (merge 6a536e2 kn/git-cd-to-empty later to maint).
>
>  * The versionsort.prerelease configuration variable can be used to
>    specify that v1.0-pre1 comes before v1.0.
>
>  * A new "push.followTags" configuration turns the "--follow-tags"
>    option on by default for the "git push" command.
>
>  * "git log --graph --no-walk A B..." is a conflicting request that
>    asks nonsense; no-walk tells us show discrete points in the
>    history, while graph asks to draw connections between these
>    discrete points. Forbid the combination.
>
>  * "git rev-list --bisect --first-parent" does not work (yet) and can
>    even cause SEGV; forbid it.  "git log --bisect --first-parent"
>    would not be useful until "git bisect --first-parent" materializes,
>    so it is also forbidden for now.
>
>
> Performance, Internal Implementation, Development Support etc.
>
>  * Implementation of N_() macro has been updated slightly to help us
>    detect mistakes.
>
>  * Implementation of "reflog expire" has been restructured to fit the
>    reflogs better with the recently updated ref API.
>
>  * The transport-helper did not give transport options such as
>    verbosity, progress, cloning, etc. to import and export based
>    helpers, like it did for fetch and push based helpers, robbing them
>    the chance to honor the wish of the end-users better.
>
>  * The tests that wanted to see that file becomes unreadable after
>    running "chmod a-r file", and the tests that wanted to make sure it
>    is not run as root, we used "can we write into the / directory?" as
>    a cheap substitute, but on some platforms that is not a good
>    heuristics.  The tests and their prerequisites have been updated to
>    check what they really require.
>    (merge f400e51 jk/sanity later to maint).
>
>  * Various issues around "reflog expire", e.g. using --updateref when
>    expiring a reflog for a symbolic reference, have been corrected
>    and/or made saner.
>
>  * The strbuf API was explained between the API documentation and in
>    the header file.  Move missing bits to strbuf.h so that programmers
>    can check only one place for all necessary information.
>
>  * The error handling functions and conventions are now documented in
>    the API manual.
>
>  * Optimize attribute look-up, mostly useful in "git grep" on a
>    project that does not use many attributes, by avoiding it when we
>    (should) know that the attributes are not defined in the first
>    place.
>
>  * Typofix in comments.
>    (merge ef2956a ak/git-pm-typofix later to maint).
>
>  * Code clean-up.
>    (merge 0b868f0 sb/hex-object-name-is-at-most-41-bytes-long later to maint).
>    (merge 5d30851 dp/remove-duplicated-header-inclusion later to maint).
>
>  * Simplify the ref transaction API around how "the ref should be
>    pointing at this object" is specified.
>
>  * Code in "git daemon" to parse out and hold hostnames used in
>    request interpolation has been simplified.
>
>  * "git push" codepath has been restructured to make it easier to add
>    new configuration bits.
>
>  * The run-command interface was easy to abuse and make a pipe for us
>    to read from the process, wait for the process to finish and then
>    attempt to read its output, which is a pattern that lead to a
>    deadlock.  Fix such uses by introducing a helper to do this
>    correctly (i.e. we need to read first and then wait the process to
>    finish) and also add code to prevent such abuse in the run-command
>    helper.
>
>  * People often forget to chain the commands in their test together
>    with &&, leaving a failure from an earlier command in the test go
>    unnoticed.  The new GIT_TEST_CHAIN_LINT mechanism allows you to
>    catch such a mistake more easily.
>
>
> Also contains various documentation updates and code clean-ups.
>
>
> Fixes since v2.3
> ----------------
>
> Unless otherwise noted, all the fixes since v2.3 in the maintenance
> track are contained in this release (see the maintenance releases'
> notes for details).
>
>  * "git blame HEAD -- missing" failed to correctly say "HEAD" when it
>    tried to say "No such path 'missing' in HEAD".
>    (merge a46442f jk/blame-commit-label later to maint).
>
>  * "git rerere" (invoked internally from many mergy operations) did
>    not correctly signal errors when told to update the working tree
>    files and failed to do so for whatever reason.
>    (merge 89ea903 jn/rerere-fail-on-auto-update-failure later to maint).
>
>  * Setting diff.submodule to 'log' made "git format-patch" produce
>    broken patches.
>    (merge 339de50 dk/format-patch-ignore-diff-submodule later to maint).
>
>  * After attempting and failing a password-less authentication
>    (e.g. Kerberos), libcURL refuses to fall back to password based
>    Basic authentication without a bit of help/encouragement.
>    (merge 4dbe664 bc/http-fallback-to-password-after-krb-fails later to maint).
>
>  * The "git push" documentation made the "--repo=<there>" option
>    easily misunderstood.
>    (merge 57b92a7 mg/push-repo-option-doc later to maint).
>
>  * Code to read branch name from various files in .git/ directory
>    would have misbehaved if the code to write them left an empty file.
>    (merge 66ec904 jk/status-read-branch-name-fix later to maint).
>
>  * A misspelled conditional that is always true has been fixed.
>    (merge 94ee8e2 jk/remote-curl-an-array-in-struct-cannot-be-null later to maint).
>
>  * The documentation incorrectly said that C(opy) and R(ename) are the
>    only ones that can be followed by the score number in the output in
>    the --raw format.
>    (merge ac1c2d9 jc/diff-format-doc later to maint).
>
>  * A broken pack .idx file in the receiving repository prevented the
>    dumb http transport from fetching a good copy of it from the other
>    side.
>    (merge 8b9c2dd jk/dumb-http-idx-fetch-fix later to maint).
>
>  * The error message from "git commit", when a non-existing author
>    name was given as value to the "--author=" parameter, has been
>    reworded to avoid misunderstanding.
>    (merge 1044b1f mg/commit-author-no-match-malformed-message later to maint).
>
>  * "git log --help" used to show rev-list options that are irrelevant
>    to the "log" command.
>    (merge 3cab02d jc/doc-log-rev-list-options later to maint).
>
>  * "git apply --whitespace=fix" used to under-allocate the memory when
>    the fix resulted in a longer text than the original patch.
>    (merge 407a792 jc/apply-ws-fix-expands later to maint).
>
>  * The interactive "show a list and let the user choose from it"
>    interface "add -i" used showed and prompted to the user even when
>    the candidate list was empty, against which the only "choice" the
>    user could have made was to choose nothing.
>    (merge a9c4641 ak/add-i-empty-candidates later to maint).
>
>  * The insn sheet "git rebase -i" creates did not fully honor
>    core.abbrev settings.
>    (merge edb72d5 ks/rebase-i-abbrev later to maint).
>
>  * "git fetch" over a remote-helper that cannot respond to "list"
>    command could not fetch from a symbolic reference e.g. HEAD.
>    (merge 33cae54 mh/deref-symref-over-helper-transport later to maint).
>
>  * "git push --signed" gave an incorrectly worded error message when
>    the other side did not support the capability.
>    (merge 45917f0 jc/push-cert later to maint).
>
>  * We didn't format an integer that wouldn't fit in "int" but in
>    "uintmax_t" correctly.
>    (merge d306f3d jk/decimal-width-for-uintmax later to maint).
>
>  * Reading configuration from a blob object, when it ends with a lone
>    CR, use to confuse the configuration parser.
>    (merge 1d0655c jk/config-no-ungetc-eof later to maint).
>
>  * The pack bitmap support did not build with older versions of GCC.
>    (merge bd4e882 jk/pack-bitmap later to maint).
>
>  * The documentation wasn't clear that "remote.<nick>.pushURL" and
>    "remote.<nick>.URL" are there to name the same repository accessed
>    via different transports, not two separate repositories.
>    (merge 697f652 jc/remote-set-url-doc later to maint).
>
>  * Older GnuPG implementations may not correctly import the keyring
>    material we prepare for the tests to use.
>    (merge 1f985d6 ch/new-gpg-drops-rfc-1991 later to maint).
>
>  * The credential helper for Windows (in contrib/) used to mishandle
>    a user name with an at-sign in it.
>    (merge 13d261e av/wincred-with-at-in-username-fix later to maint).
>
>  * "diff-highlight" (in contrib/) used to show byte-by-byte
>    differences, which meant that multi-byte characters can be chopped
>    in the middle.  It learned to pay attention to character boundaries
>    (assuming the UTF-8 payload).
>    (merge 8d00662 jk/colors later to maint).
>
>  * "git merge --quiet" did not squelch messages from the underlying
>    merge-recursive strategy.
>    (merge 2bf15a3 jk/merge-quiet later to maint).
>
>  * Longstanding configuration variable naming rules has been added to
>    the documentation.
>    (merge 35840a3 jc/conf-var-doc later to maint).
>
>  * An earlier workaround to squelch unhelpful deprecation warnings
>    from the compiler on Mac OSX unnecessarily set minimum required
>    version of the OS, which the user might want to raise (or lower)
>    for other reasons.
>    (merge 88c03eb es/squelch-openssl-warnings-on-macosx later to maint).
>
>  * Certain older vintages of cURL give irregular output from
>    "curl-config --vernum", which confused our build system.
>    (merge 3af6792 tc/curl-vernum-output-broken-in-7.11 later to maint).
>
>  * In v2.2.0, we broke "git prune" that runs in a repository that
>    borrows from an alternate object store.
>    (merge b0a4264 jk/prune-mtime later to maint).
>
>  * "git submodule add" failed to squash "path/to/././submodule" to
>    "path/to/submodule".
>    (merge 8196e72 ps/submodule-sanitize-path-upon-add later to maint).
>
>  * "git merge-file" did not work correctly in a subdirectory.
>    (merge 204a8ff ab/merge-file-prefix later to maint).
>
>  * "git blame" died, trying to free an uninitialized piece of memory.
>    (merge e600592 es/blame-commit-info-fix later to maint).
>
>  * "git fast-import" used to crash when it could not close and
>    conclude the resulting packfile cleanly.
>    (merge 5e915f3 jk/fast-import-die-nicely-fix later to maint).
>
>  * "update-index --refresh" used to leak when an entry cannot be
>    refreshed for whatever reason.
>    (merge bc1c2ca sb/plug-leak-in-make-cache-entry later to maint).
>
>  * The "interpolated-path" option of "git daemon" inserted any string
>    client declared on the "host=" capability request without checking.
>    Sanitize and limit %H and %CH to a saner and a valid DNS name.
>    (merge b485373 jk/daemon-interpolate later to maint).
>
>  * "git daemon" looked up the hostname even when "%CH" and "%IP"
>    interpolations are not requested, which was unnecessary.
>    (merge dc8edc8 rs/daemon-interpolate later to maint).
>
>  * Even though we officially haven't dropped Perl 5.8 support, the
>    Getopt::Long package that came with it does not support "--no-"
>    prefix to negate a boolean option; manually add support to help
>    people with older Getopt::Long package.
>    (merge f471494 km/send-email-getopt-long-workarounds later to maint).
>
>  * "git apply" was not very careful about reading from, removing,
>    updating and creating paths outside the working tree (under
>    --index/--cached) or the current directory (when used as a
>    replacement for GNU patch).
>    (merge e0d201b jc/apply-beyond-symlink later to maint).
>
>  * A breakage to git-svn around v2.2 era that triggers premature
>    closing of FileHandle has been corrected.
>    (merge e426311 ew/svn-maint-fixes later to maint).
>
>  * We did not parse username followed by literal IPv6 address in SSH
>    transport URLs, e.g. ssh://user@[2001:db8::1]:22/repo.git
>    correctly.
>    (merge 6b6c5f7 tb/connect-ipv6-parse-fix later to maint).
>
>  * The configuration variable 'mailinfo.scissors' was hard to
>    discover in the documentation.
>    (merge afb5de7 mm/am-c-doc later to maint).
>
>  * The interaction between "git submodule update" and the
>    submodule.*.update configuration was not clearly documented.
>    (merge 5c31acf ms/submodule-update-config-doc later to maint).
>
>  * "git diff --shortstat --dirstat=changes" showed a dirstat based on
>    lines that was never asked by the end user in addition to the
>    dirstat that the user asked for.
>    (merge ab27389 mk/diff-shortstat-dirstat-fix later to maint).
>
>  * "git remote add" mentioned "--tags" and "--no-tags" and was not
>    clear that fetch from the remote in the future will use the default
>    behaviour when neither is given to override it.
>    (merge aaba0ab mg/doc-remote-tags-or-not later to maint).
>
>  * Description given by "grep -h" for its --exclude-standard option
>    was phrased poorly.
>    (merge 77fdb8a nd/grep-exclude-standard-help-fix later to maint).
>
>  * "git rebase -i" recently started to include the number of
>    commits in the insn sheet to be processed, but on a platform
>    that prepends leading whitespaces to "wc -l" output, the numbers
>    are shown with extra whitespaces that aren't necessary.
>    (merge 2185d3b es/rebase-i-count-todo later to maint).
>
>  * The borrowed code in kwset API did not follow our usual convention
>    to use "unsigned char" to store values that range from 0-255.
>    (merge 189c860 bw/kwset-use-unsigned later to maint).
>
>  * A corrupt input to "git diff -M" used to cause it to segfault.
>    (merge 4d6be03 jk/diffcore-rename-duplicate later to maint).
>
>  * Certain builds of GPG triggered false breakages in a test.
>    (merge 3f88c1b mg/verify-commit later to maint).
>
>  * "git imap-send" learned to optionally talk with an IMAP server via
>    libcURL; because there is no other option when Git is built with
>    NO_OPENSSL option, use that codepath by default under such
>    configuration.
>    (merge dcd01ea km/imap-send-libcurl-options later to maint).
>
>  * "git log --decorate" did not reset colors correctly around the
>    branch names.
>    (merge 5ee8758 jc/decorate-leaky-separator-color later to maint).
>
>  * The code that reads from the ctags file in the completion script
>    (in contrib/) did not spell ${param/pattern/string} substitution
>    correctly, which happened to work with bash but not with zsh.
>    (merge db8d750 js/completion-ctags-pattern-substitution-fix later to maint).
>
>  * The transfer.hiderefs support did not quite work for smart-http
>    transport.
>    (merge 8ddf3ca jk/smart-http-hide-refs later to maint).
>
>  * "git tag -h" used to show the "--column" and "--sort" options
>    that are about listing in a wrong section.
>    (merge dd059c6 jk/tag-h-column-is-a-listing-option later to maint).
>
>  * "git prune" used to largely ignore broken refs when deciding which
>    objects are still being used, which could spread an existing small
>    damage and make it a larger one.
>    (merge ea56c4e jk/prune-with-corrupt-refs later to maint).
>
>  * The split-index mode introduced at v2.3.0-rc0~41 was broken in the
>    codepath to protect us against a broken reimplementation of Git
>    that writes an invalid index with duplicated index entries, etc.
>    (merge 03f15a7 tg/fix-check-order-with-split-index later to maint).
>
>  * "git fetch" that fetches a commit using the allow-tip-sha1-in-want
>    extension could have failed to fetch all the requested refs.
>    (merge 32d0462 jk/fetch-pack later to maint).
>
>  * An failure early in the "git clone" that started creating the
>    working tree and repository could have resulted in some directories
>    and files left without getting cleaned up.
>    (merge 16eff6c jk/cleanup-failed-clone later to maint).
>
>  * Recommend format-patch and send-email for those who want to submit
>    patches to this project.
>    (merge b25c469 jc/submitting-patches-mention-send-email later to maint).
>
>  * Even though "git grep --quiet" is run merely to ask for the exit
>    status, we spawned the pager regardless.  Stop doing that.
>    (merge c2048f0 ws/grep-quiet-no-pager later to maint).
>
>  * The prompt script (in contrib/) did not show the untracked sign
>    when working in a subdirectory without any untracked files.
>    (merge 9bdc517 ct/prompt-untracked-fix later to maint).
>
>  * Code cleanups and documentation updates.
>    (merge 2ce63e9 rs/simple-cleanups later to maint).
>    (merge 33baa69 rj/no-xopen-source-for-cygwin later to maint).
>    (merge 817d03e jc/diff-test-updates later to maint).
>    (merge eb32c66 ak/t5516-typofix later to maint).
>    (merge bcd57cb mr/doc-clean-f-f later to maint).
>    (merge 0d6accc mg/doc-status-color-slot later to maint).
>    (merge 53e53c7 sg/completion-remote later to maint).
>    (merge 8fa7975 ak/git-done-help-cleanup later to maint).
>    (merge 9a6f128 rs/deflate-init-cleanup later to maint).
>    (merge 6f75d45 rs/use-isxdigit later to maint).
>    (merge 376e4b3 jk/test-annoyances later to maint).
>    (merge 7032054 nd/doc-git-index-version later to maint).
>    (merge e869c5e tg/test-index-v4 later to maint).
>    (merge 599d223 jk/simplify-csum-file-sha1fd-check later to maint).
>    (merge 260d585 sg/completion-gitcomp-nl-for-refs later to maint).
>    (merge 777c55a jc/report-path-error-to-dir later to maint).
>    (merge fddfaf8 ph/push-doc-cas later to maint).
>    (merge d50d31e ss/pull-rebase-preserve later to maint).
>    (merge c8c3f1d pt/enter-repo-comment-fix later to maint).
>    (merge d7bfb9e jz/gitweb-conf-doc-fix later to maint).
>    (merge f907282 jk/cherry-pick-docfix later to maint).
>    (merge d3c0811 iu/fix-parse-options-h-comment later to maint).
>    (merge 6c3b2af jg/cguide-we-cannot-count later to maint).
>    (merge 2b8bd44 jk/pack-corruption-post-mortem later to maint).
>    (merge 9585cb8 jn/doc-fast-import-no-16-octopus-limit later to maint).
>
> ----------------------------------------------------------------
>
> Changes since v2.4.0-rc1 are as follows:
>
> Alex Henrie (2):
>       l10n: ca.po: update translation
>       l10n: ca.po: update translation
>
> Alexander Shopov (1):
>       l10n: Updated Bulgarian translation of git (2305t,0f,0u)
>
> Dimitriy Ryazantcev (3):
>       l10n: ru: added Russian translation
>       l10n: ru: updated Russian translation
>       l10n: ru: updated Russian translation
>
> Ivan Ukhov (1):
>       parse-options.h: OPTION_{BIT,SET_INT} do not store pointer to defval
>
> Jean-Noel Avila (2):
>       l10n: fr.po v2.4.0-rc0 round 1
>       l10n: fr.po v2.4.0 round 2
>
> Jeff King (3):
>       cherry-pick: fix docs describing handling of empty commits
>       howto: document more tools for recovery corruption
>       merge: pass verbosity flag down to merge-recursive

I'm pretty confident this change is working as intended, but the
intended change is causing a regression in behavior for me. I'll
readily admit that my workflow is probably wrong, but I thought
perhaps it would be worth surfacing.

Aphrael:git bturner$ git bisect bad
2bf15a3330a26183adc8563dbeeacc11294b8a01 is the first bad commit
commit 2bf15a3330a26183adc8563dbeeacc11294b8a01
Author: Jeff King <peff@peff.net>
Date:   Thu Apr 2 17:39:52 2015 -0400

    merge: pass verbosity flag down to merge-recursive

When I merge two branches with a submodule conflict on 2.4.0-rc1 I get
the following output:
Aphrael:test-merge bturner$ /opt/local/git/2.4.0-rc1/bin/git merge -m
"branch_that_has_submodule_at_different_commit_src merge" --no-ff
--log --quiet ee85213ec42077581cc408fee21cf2dc2278858b
(stderr) warning: Failed to merge submodule submodule (not checked out)
(stdout) Auto-merging submodule
(stdout) CONFLICT (submodule): Merge conflict in submodule
(stdout) Automatic merge failed; fix conflicts and then commit the result.

With this change applied, in v2.4.0-rc2 I now get:
Aphrael:test-merge bturner$ /opt/local/git/2.4.0-rc1/bin/git merge -m
"branch_that_has_submodule_at_different_commit_src merge" --no-ff
--log --quiet ee85213ec42077581cc408fee21cf2dc2278858b
(stderr) warning: Failed to merge submodule submodule (not checked out)
(stdout) Automatic merge failed; fix conflicts and then commit the result.

(Any conflict will lose the "Auto-merging" and "CONFLICT" lines; I'm
singling out submodule conflicts here just because they also have the
"not checked out" line)

If the goal of passing the verbosity flag down was to fix git merge
--quiet, should the "Automatic merge failed" line also be omitted? But
if that line should _stay_, wouldn't it be better for the "CONFLICT"
lines to also stay?

For what it's worth, dropping the "CONFLICT" lines for --quiet breaks
the pull request functionality in Atlassian Stash, which is parsing
them from stdout. Please note that I'm _not_ saying Git shouldn't make
a desirable change because of a problem in Stash; we'll fix Stash to
expect whatever behavior change is applied. That just means
administrators who upgrade to Git 2.4 will also need to upgrade Stash,
and the mode of failure for them will be very subtle.

>
>
> Jiang Xin (5):
>       l10n: git.pot: v2.4.0 round 1 (99 new, 92 removed)
>       l10n: zh_CN: translations for git v2.4.0-rc0
>       l10n: git.pot: v2.4.0 round 2 (1 update)
>       l10n: zh_CN: for git v2.4.0 l10n round 2
>       l10n: TEAMS: Change repository URL of zh_CN
>
> John Keeping (1):
>       streaming.c: fix a memleak
>
> Jonathan Nieder (1):
>       fast-import doc: remove suggested 16-parent limit
>
> Julian Gindi (1):
>       CodingGuidelines: update 'rough' rule count
>
> Junio C Hamano (2):
>       push-to-deploy: allow pushing into an unborn branch and updating it
>       Git 2.4.0-rc2
>
> Jérôme Zago (1):
>       gitweb.conf.txt: say "build-time", not "built-time"
>
> Kyle J. McKay (1):
>       diff-highlight: do not split multibyte characters
>
> Matthias Rüster (1):
>       l10n: de.po: translate 'symbolic link' as 'symbolische Verknüpfung'
>
> Michael J Gruber (1):
>       l10n: de.po: fix negation for commit -a with paths
>
> Paul Tan (1):
>       enter_repo(): fix docs to match code
>
> Peter Krefting (2):
>       l10n: sv.po: Update Swedish translation (2305t0f0u)
>       l10n: sv.po: Update Swedish translation (2305t0f0u)
>
> Phillip Sz (1):
>       l10n: de.po: add space before ellipsis
>
> Ralf Thielow (3):
>       l10n: de.po: fix messages with abbreviated hashs
>       l10n: de.po: translate 99 new messages
>       l10n: de.po: translate one message
>
> Stefan Beller (1):
>       wt-status.c: fix a memleak
>
> Trần Ngọc Quân (2):
>       l10n: vi.po: Updated Vietnamese translation
>       l10n: vi.po(2305t): Updated 1 new string
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 3%]

* Re: [PATCH v2 02/16] refs: convert for_each_tag_ref to struct object_id
  @ 2015-04-23 18:13  2%   ` Stefan Beller
  2015-04-23 19:27  4%     ` Jeff King
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-04-23 18:13 UTC (permalink / raw)
  To: brian m. carlson
  Cc: git@vger.kernel.org, Jeff King, Michael Haggerty, Junio C Hamano,
	Kyle J. McKay, Ronnie Sahlberg

On Wed, Apr 22, 2015 at 4:24 PM, brian m. carlson
<sandals@crustytoothpaste.net> wrote:
> To allow piecemeal conversion of the for_each_*_ref functions, introduce
> an additional typedef for a callback function that takes struct
> object_id * instead of unsigned char *.  Provide an extra field in
> struct ref_entry_cb for this callback and ensure at most one is set at a
> time.  Temporarily suffix these new entries with _oid to distinguish
> them.  Convert for_each_tag_ref and its callers to use the new _oid
> functions, introducing temporary wrapper functions to avoid type
> mismatches.
>
> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>

I am currently running this patch series via
git rebase -i origin/next --exec=make --exec="make test"
through the compilation and test suite one by one.
(My current view of origin/next is (c8da2d582, Sync with 2.4.0-rc3)
and this commit fails in t5312-prune-corruption.sh test 3 5 and 8

> ---
>  builtin/pack-objects.c |  4 ++--
>  builtin/rev-parse.c    |  7 ++++++-
>  builtin/tag.c          |  8 ++++----
>  refs.c                 | 34 ++++++++++++++++++++++++++++++----
>  refs.h                 | 10 +++++++++-
>  5 files changed, 51 insertions(+), 12 deletions(-)
>
> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> index c067107..0c69b0c 100644
> --- a/builtin/pack-objects.c
> +++ b/builtin/pack-objects.c
> @@ -540,11 +540,11 @@ static enum write_one_status write_one(struct sha1file *f,
>         return WRITE_ONE_WRITTEN;
>  }
>
> -static int mark_tagged(const char *path, const unsigned char *sha1, int flag,
> +static int mark_tagged(const char *path, const struct object_id *oid, int flag,
>                        void *cb_data)
>  {
>         unsigned char peeled[20];
> -       struct object_entry *entry = packlist_find(&to_pack, sha1, NULL);
> +       struct object_entry *entry = packlist_find(&to_pack, oid->hash, NULL);
>
>         if (entry)
>                 entry->tagged = 1;
> diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
> index 4d10dd9..7b70650 100644
> --- a/builtin/rev-parse.c
> +++ b/builtin/rev-parse.c
> @@ -198,6 +198,11 @@ static int show_reference(const char *refname, const unsigned char *sha1, int fl
>         return 0;
>  }
>
> +static int show_reference_oid(const char *refname, const struct object_id *oid, int flag, void *cb_data)
> +{
> +       return show_reference(refname, oid->hash, flag, cb_data);
> +}
> +
>  static int anti_reference(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
>  {
>         show_rev(REVERSED, sha1, refname);
> @@ -682,7 +687,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
>                                 continue;
>                         }
>                         if (!strcmp(arg, "--tags")) {
> -                               for_each_tag_ref(show_reference, NULL);
> +                               for_each_tag_ref(show_reference_oid, NULL);
>                                 clear_ref_exclusion(&ref_excludes);
>                                 continue;
>                         }
> diff --git a/builtin/tag.c b/builtin/tag.c
> index 6f07ac6..61399b7 100644
> --- a/builtin/tag.c
> +++ b/builtin/tag.c
> @@ -215,7 +215,7 @@ free_return:
>         free(buf);
>  }
>
> -static int show_reference(const char *refname, const unsigned char *sha1,
> +static int show_reference(const char *refname, const struct object_id *oid,
>                           int flag, void *cb_data)
>  {
>         struct tag_filter *filter = cb_data;
> @@ -224,14 +224,14 @@ static int show_reference(const char *refname, const unsigned char *sha1,
>                 if (filter->with_commit) {
>                         struct commit *commit;
>
> -                       commit = lookup_commit_reference_gently(sha1, 1);
> +                       commit = lookup_commit_reference_gently(oid->hash, 1);
>                         if (!commit)
>                                 return 0;
>                         if (!contains(commit, filter->with_commit))
>                                 return 0;
>                 }
>
> -               if (points_at.nr && !match_points_at(refname, sha1))
> +               if (points_at.nr && !match_points_at(refname, oid->hash))
>                         return 0;
>
>                 if (!filter->lines) {
> @@ -242,7 +242,7 @@ static int show_reference(const char *refname, const unsigned char *sha1,
>                         return 0;
>                 }
>                 printf("%-15s ", refname);
> -               show_tag_lines(sha1, filter->lines);
> +               show_tag_lines(oid->hash, filter->lines);
>                 putchar('\n');
>         }
>
> diff --git a/refs.c b/refs.c
> index 522d15d..95863f2 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -694,6 +694,7 @@ struct ref_entry_cb {
>         int trim;
>         int flags;
>         each_ref_fn *fn;
> +       each_ref_fn_oid *fn_oid;
>         void *cb_data;
>  };
>
> @@ -717,8 +718,13 @@ static int do_one_ref(struct ref_entry *entry, void *cb_data)
>         /* Store the old value, in case this is a recursive call: */
>         old_current_ref = current_ref;
>         current_ref = entry;
> -       retval = data->fn(entry->name + data->trim, entry->u.value.oid.hash,
> -                         entry->flag, data->cb_data);
> +       if (data->fn_oid) {
> +               retval = data->fn_oid(entry->name + data->trim, &entry->u.value.oid,
> +                                entry->flag, data->cb_data);
> +       } else {
> +               retval = data->fn(entry->name + data->trim, entry->u.value.oid.hash,
> +                                entry->flag, data->cb_data);
> +       }
>         current_ref = old_current_ref;
>         return retval;
>  }
> @@ -1950,6 +1956,21 @@ static int do_for_each_ref(struct ref_cache *refs, const char *base,
>         data.trim = trim;
>         data.flags = flags;
>         data.fn = fn;
> +       data.fn_oid = NULL;
> +       data.cb_data = cb_data;
> +
> +       return do_for_each_entry(refs, base, do_one_ref, &data);
> +}
> +
> +static int do_for_each_ref_oid(struct ref_cache *refs, const char *base,
> +                          each_ref_fn_oid fn, int trim, int flags, void *cb_data)
> +{
> +       struct ref_entry_cb data;
> +       data.base = base;
> +       data.trim = trim;
> +       data.flags = flags;
> +       data.fn = NULL;
> +       data.fn_oid = fn;
>         data.cb_data = cb_data;
>
>         if (ref_paranoia < 0)
> @@ -1998,6 +2019,11 @@ int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
>         return do_for_each_ref(get_ref_cache(submodule), "", fn, 0, 0, cb_data);
>  }
>
> +static int for_each_ref_in_oid(const char *prefix, each_ref_fn_oid fn, void *cb_data)
> +{
> +       return do_for_each_ref_oid(&ref_cache, prefix, fn, strlen(prefix), 0, cb_data);
> +}
> +
>  int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
>  {
>         return do_for_each_ref(&ref_cache, prefix, fn, strlen(prefix), 0, cb_data);
> @@ -2009,9 +2035,9 @@ int for_each_ref_in_submodule(const char *submodule, const char *prefix,
>         return do_for_each_ref(get_ref_cache(submodule), prefix, fn, strlen(prefix), 0, cb_data);
>  }
>
> -int for_each_tag_ref(each_ref_fn fn, void *cb_data)
> +int for_each_tag_ref(each_ref_fn_oid fn, void *cb_data)
>  {
> -       return for_each_ref_in("refs/tags/", fn, cb_data);
> +       return for_each_ref_in_oid("refs/tags/", fn, cb_data);
>  }
>
>  int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
> diff --git a/refs.h b/refs.h
> index 6d7d9b4..b83529b 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -1,6 +1,8 @@
>  #ifndef REFS_H
>  #define REFS_H
>
> +#include "cache.h"
> +
>  /*
>   * A ref_transaction represents a collection of ref updates
>   * that should succeed or fail together.
> @@ -70,6 +72,12 @@ typedef int each_ref_fn(const char *refname,
>                         const unsigned char *sha1, int flags, void *cb_data);
>
>  /*
> + * Like each_ref_fn, but passes the object ID using a struct.
> + */
> +typedef int each_ref_fn_oid(const char *refname,
> +                       const struct object_id *oid, int flags, void *cb_data);
> +
> +/*
>   * The following functions invoke the specified callback function for
>   * each reference indicated.  If the function ever returns a nonzero
>   * value, stop the iteration and return that value.  Please note that
> @@ -81,7 +89,7 @@ typedef int each_ref_fn(const char *refname,
>  extern int head_ref(each_ref_fn, void *);
>  extern int for_each_ref(each_ref_fn, void *);
>  extern int for_each_ref_in(const char *, each_ref_fn, void *);
> -extern int for_each_tag_ref(each_ref_fn, void *);
> +extern int for_each_tag_ref(each_ref_fn_oid, void *);
>  extern int for_each_branch_ref(each_ref_fn, void *);
>  extern int for_each_remote_ref(each_ref_fn, void *);
>  extern int for_each_replace_ref(each_ref_fn, void *);
> --
> 2.3.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 2%]

* Re: [PATCH v2 02/16] refs: convert for_each_tag_ref to struct object_id
  2015-04-23 18:13  2%   ` Stefan Beller
@ 2015-04-23 19:27  4%     ` Jeff King
  0 siblings, 0 replies; 200+ results
From: Jeff King @ 2015-04-23 19:27 UTC (permalink / raw)
  To: Stefan Beller
  Cc: brian m. carlson, git@vger.kernel.org, Michael Haggerty,
	Junio C Hamano, Kyle J. McKay, Ronnie Sahlberg

On Thu, Apr 23, 2015 at 11:13:32AM -0700, Stefan Beller wrote:

> On Wed, Apr 22, 2015 at 4:24 PM, brian m. carlson
> <sandals@crustytoothpaste.net> wrote:
> > To allow piecemeal conversion of the for_each_*_ref functions, introduce
> > an additional typedef for a callback function that takes struct
> > object_id * instead of unsigned char *.  Provide an extra field in
> > struct ref_entry_cb for this callback and ensure at most one is set at a
> > time.  Temporarily suffix these new entries with _oid to distinguish
> > them.  Convert for_each_tag_ref and its callers to use the new _oid
> > functions, introducing temporary wrapper functions to avoid type
> > mismatches.
> >
> > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
> 
> I am currently running this patch series via
> git rebase -i origin/next --exec=make --exec="make test"
> through the compilation and test suite one by one.
> (My current view of origin/next is (c8da2d582, Sync with 2.4.0-rc3)
> and this commit fails in t5312-prune-corruption.sh test 3 5 and 8

It's because of this hunk:

> > @@ -1950,6 +1956,21 @@ static int do_for_each_ref(struct ref_cache *refs, const char *base,
> >         data.trim = trim;
> >         data.flags = flags;
> >         data.fn = fn;
> > +       data.fn_oid = NULL;
> > +       data.cb_data = cb_data;
> > +
> > +       return do_for_each_entry(refs, base, do_one_ref, &data);
> > +}
> > +
> > +static int do_for_each_ref_oid(struct ref_cache *refs, const char *base,
> > +                          each_ref_fn_oid fn, int trim, int flags, void *cb_data)
> > +{
> > +       struct ref_entry_cb data;
> > +       data.base = base;
> > +       data.trim = trim;
> > +       data.flags = flags;
> > +       data.fn = NULL;
> > +       data.fn_oid = fn;
> >         data.cb_data = cb_data;
> >
> >         if (ref_paranoia < 0)

The ref_paranoia code gets pushed down into do_for_each_ref_oid, but it
needs called in both do_for_each_ref variants. This is probably an
artifact of rebasing the patches (the ref_paranoia stuff was added
recently).

I think it would make sense to pull the setup of the data struct into a
shared function rather than duplicate it. But we want to avoid having to
update do_for_each_ref callsites, so we'll have to provide a wrapper.

Like this:

diff --git a/refs.c b/refs.c
index 95863f2..ad39d74 100644
--- a/refs.c
+++ b/refs.c
@@ -1948,29 +1948,16 @@ static int do_for_each_entry(struct ref_cache *refs, const char *base,
  * value, stop the iteration and return that value; otherwise, return
  * 0.
  */
-static int do_for_each_ref(struct ref_cache *refs, const char *base,
-			   each_ref_fn fn, int trim, int flags, void *cb_data)
+static int do_for_each_ref_generic(struct ref_cache *refs, const char *base,
+				   each_ref_fn fn, each_ref_fn_oid fn_oid,
+				   int trim, int flags, void *cb_data)
 {
 	struct ref_entry_cb data;
 	data.base = base;
 	data.trim = trim;
 	data.flags = flags;
 	data.fn = fn;
-	data.fn_oid = NULL;
-	data.cb_data = cb_data;
-
-	return do_for_each_entry(refs, base, do_one_ref, &data);
-}
-
-static int do_for_each_ref_oid(struct ref_cache *refs, const char *base,
-			   each_ref_fn_oid fn, int trim, int flags, void *cb_data)
-{
-	struct ref_entry_cb data;
-	data.base = base;
-	data.trim = trim;
-	data.flags = flags;
-	data.fn = NULL;
-	data.fn_oid = fn;
+	data.fn_oid = fn_oid;
 	data.cb_data = cb_data;
 
 	if (ref_paranoia < 0)
@@ -1981,6 +1968,18 @@ static int do_for_each_ref_oid(struct ref_cache *refs, const char *base,
 	return do_for_each_entry(refs, base, do_one_ref, &data);
 }
 
+static int do_for_each_ref(struct ref_cache *refs, const char *base,
+			   each_ref_fn fn, int trim, int flags, void *cb_data)
+{
+	return do_for_each_ref_generic(refs, base, fn, NULL, trim, flags, cb_data);
+}
+
+static int do_for_each_ref_oid(struct ref_cache *refs, const char *base,
+			       each_ref_fn_oid fn, int trim, int flags, void *cb_data)
+{
+	return do_for_each_ref_generic(refs, base, NULL, fn, trim, flags, cb_data);
+}
+
 static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)
 {
 	unsigned char sha1[20];

You can even dispense with the _oid variant wrapper, and just call into
the generic version directly from the new callsites.

-Peff

^ permalink raw reply related	[relevance 4%]

* Re: [PATCH v5 1/5] setup: add gentle version of read_gitfile
  @ 2015-04-29 23:47  2%     ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-04-29 23:47 UTC (permalink / raw)
  To: Erik Elfström; +Cc: git@vger.kernel.org, Junio C Hamano

On Sat, Apr 25, 2015 at 11:49 PM, Erik Elfström <erik.elfstrom@gmail.com> wrote:
> read_gitfile will die on most error cases. This makes it unsuitable
> for speculative calls. Extract the core logic and provide a gentle
> version that returns NULL on failure.
>
> The first usecase of the new gentle version will be to probe for
> submodules during git clean.
>
> Helped-by: Junio C Hamano <gitster@pobox.com>
> Helped-by: Jeff King <peff@peff.net>
> Signed-off-by: Erik Elfström <erik.elfstrom@gmail.com>
> ---
>  cache.h | 11 ++++++++-
>  setup.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++--------------
>  2 files changed, 75 insertions(+), 18 deletions(-)
>
> diff --git a/cache.h b/cache.h
> index 3d3244b..868e4d3 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -431,7 +431,16 @@ extern int set_git_dir(const char *path);
>  extern const char *get_git_namespace(void);
>  extern const char *strip_namespace(const char *namespaced_ref);
>  extern const char *get_git_work_tree(void);
> -extern const char *read_gitfile(const char *path);
> +
> +#define READ_GITFILE_ERR_STAT_FAILED 1
> +#define READ_GITFILE_ERR_NOT_A_FILE 2
> +#define READ_GITFILE_ERR_OPEN_FAILED 3
> +#define READ_GITFILE_ERR_READ_FAILED 4
> +#define READ_GITFILE_ERR_INVALID_FORMAT 5
> +#define READ_GITFILE_ERR_NO_PATH 6
> +#define READ_GITFILE_ERR_NOT_A_REPO 7
> +extern const char *read_gitfile_gently(const char *path, int *return_error_code);
> +#define read_gitfile(path) read_gitfile_gently((path), NULL)
>  extern const char *resolve_gitdir(const char *suspect);
>  extern void set_git_work_tree(const char *tree);
>
> diff --git a/setup.c b/setup.c
> index 979b13f..c4538ca 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -335,35 +335,53 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
>  /*
>   * Try to read the location of the git directory from the .git file,
>   * return path to git directory if found.
> + *
> + * On failure, if return_error_code is not NULL, return_error_code
> + * will be set to an error code and NULL will be returned. If
> + * return_error_code is NULL the function will die instead (for most
> + * cases).
>   */
> -const char *read_gitfile(const char *path)
> +const char *read_gitfile_gently(const char *path, int *return_error_code)
>  {
> -       char *buf;
> -       char *dir;
> +       int error_code = 0;
> +       char *buf = NULL;
> +       char *dir = NULL;
>         const char *slash;
>         struct stat st;
>         int fd;
>         ssize_t len;
>
> -       if (stat(path, &st))
> -               return NULL;
> -       if (!S_ISREG(st.st_mode))
> -               return NULL;
> +       if (stat(path, &st)) {
> +               error_code = READ_GITFILE_ERR_STAT_FAILED;
> +               goto cleanup_return;
> +       }
> +       if (!S_ISREG(st.st_mode)) {
> +               error_code = READ_GITFILE_ERR_NOT_A_FILE;
> +               goto cleanup_return;
> +       }
>         fd = open(path, O_RDONLY);
> -       if (fd < 0)
> -               die_errno("Error opening '%s'", path);
> +       if (fd < 0) {
> +               error_code = READ_GITFILE_ERR_OPEN_FAILED;
> +               goto cleanup_return;
> +       }
>         buf = xmalloc(st.st_size + 1);
>         len = read_in_full(fd, buf, st.st_size);
>         close(fd);
> -       if (len != st.st_size)
> -               die("Error reading %s", path);
> +       if (len != st.st_size) {
> +               error_code = READ_GITFILE_ERR_READ_FAILED;
> +               goto cleanup_return;

Sorry for the late review.

So when you jump from here to the cleanup, there is no close(fd) involved?
I think there are code paths now, which leak fd.

> +       }
>         buf[len] = '\0';
> -       if (!starts_with(buf, "gitdir: "))
> -               die("Invalid gitfile format: %s", path);
> +       if (!starts_with(buf, "gitdir: ")) {
> +               error_code = READ_GITFILE_ERR_INVALID_FORMAT;
> +               goto cleanup_return;
> +       }
>         while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
>                 len--;
> -       if (len < 9)
> -               die("No path in gitfile: %s", path);
> +       if (len < 9) {
> +               error_code = READ_GITFILE_ERR_NO_PATH;
> +               goto cleanup_return;
> +       }
>         buf[len] = '\0';
>         dir = buf + 8;
>
> @@ -378,11 +396,41 @@ const char *read_gitfile(const char *path)
>                 buf = dir;
>         }
>
> -       if (!is_git_directory(dir))
> -               die("Not a git repository: %s", dir);
> +       if (!is_git_directory(dir)) {
> +               error_code = READ_GITFILE_ERR_NOT_A_REPO;
> +               goto cleanup_return;
> +       }
>         path = real_path(dir);
>
> +cleanup_return:
>         free(buf);
> +
> +       if (return_error_code)
> +               *return_error_code = error_code;
> +
> +       if (error_code) {
> +               if (return_error_code)
> +                       return NULL;
> +
> +               switch (error_code) {
> +               case READ_GITFILE_ERR_STAT_FAILED:
> +               case READ_GITFILE_ERR_NOT_A_FILE:
> +                       return NULL;
> +               case READ_GITFILE_ERR_OPEN_FAILED:
> +                       die_errno("Error opening '%s'", path);
> +               case READ_GITFILE_ERR_READ_FAILED:
> +                       die("Error reading %s", path);
> +               case READ_GITFILE_ERR_INVALID_FORMAT:
> +                       die("Invalid gitfile format: %s", path);
> +               case READ_GITFILE_ERR_NO_PATH:
> +                       die("No path in gitfile: %s", path);
> +               case READ_GITFILE_ERR_NOT_A_REPO:
> +                       die("Not a git repository: %s", dir);
> +               default:
> +                       assert(0);
> +               }
> +       }
> +
>         return path;
>  }
>
> --
> 2.4.0.rc3.8.gbb31afb
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 2%]

* [ANNOUNCE] Git v2.4.0
@ 2015-04-30 19:51  2% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-04-30 19:51 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

The latest feature release Git v2.4.0 is now available at the
usual places.  It is comprised of 426 non-merge commits since
v2.3.0, contributed by 76 people, 25 of which are new faces.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/

The following public repositories all have a copy of the 'v2.4.0'
tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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

New contributors whose contributions weren't in v2.3.0 are as follows.
Welcome to the Git development community!

  Aleksander Boruch-Gruszecki, Aleksey Vasenev, Christoph Junghans,
  Cody A Taylor, Csaba Kiraly, Dimitriy Ryazantcev, Dongcan Jiang,
  Doug Kelly, Gabriele Mazzotta, Henri GEIST, Ivan Ukhov, Jérôme
  Zago, Julian Gindi, Karthik Nayak, Kevin Daudt, Márcio Almada,
  Matthias Rüster, Michael Lutz, Mikko Rapeli, Patrick Steinhardt,
  Paul Tan, Remi Rampin, Ryuichi Kokubo, Tom G. Christensen,
  and Wilhelm Schuermann.

Returning contributors who helped this release are as follows.
Thanks for your continued support.

  Alexander Kuleshov, Alexander Shopov, Alex Henrie, Anders
  Kaseorg, Ben Walton, brian m. carlson, Chris Packham, Dave
  Olszewski, David Turner, Eric Sunshine, Eric Wong, Jean-Noel
  Avila, Jeff King, Jiang Xin, Johannes Sixt, John Keeping,
  John Szakmeister, Jonathan Nieder, Jonathon Mah, Junio C
  Hamano, Kirill A. Shutemov, Kyle J. McKay, Lukas Fleischer,
  Luke Diamand, Mårten Kongstad, Matthieu Moy, Max Kirillov,
  Michael Haggerty, Michael J Gruber, Michal Sojka, Mike Hommey,
  Nguyễn Thái Ngọc Duy, Pat Thoyts, Paul Mackerras, Peter
  Krefting, Phil Hord, Phillip Sz, Ralf Thielow, Ramsay Allan
  Jones, René Scharfe, Ronnie Sahlberg, Sebastian Schuberth,
  Stefan Beller, SZEDER Gábor, Thomas Ackermann, Thomas Gummerer,
  Torsten Bögershausen, Trần Ngọc Quân, Vitor Antunes,
  Yi EungJun, and Дилян Палаузов.

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

Git 2.4 Release Notes
=====================

Backward compatibility warning(s)
---------------------------------

This release has a few changes in the user-visible output from
Porcelain commands. These are not meant to be parsed by scripts, but
users still may want to be aware of the changes:

 * The output from "git log --decorate" (and, more generally, the "%d"
   format specifier used in the "--format=<string>" parameter to the
   "git log" family of commands) has changed. It used to list "HEAD"
   just like other branches; e.g.,

     $ git log --decorate -1 master
     commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD, master)
     ...

   This release changes the output slightly when HEAD refers to a
   branch whose name is also shown in the output. The above is now
   shown as:

     $ git log --decorate -1 master
     commit bdb0f6788fa5e3cacc4315e9ff318a27b2676ff4 (HEAD -> master)
     ...

 * The phrasing "git branch" uses to describe a detached HEAD has been
   updated to agree with the phrasing used by "git status":

    - When HEAD is at the same commit as when it was originally
      detached, they now both show "detached at <commit object name>".

    - When HEAD has moved since it was originally detached, they now
      both show "detached from <commit object name>".

   Previously, "git branch" always used "from".


Updates since v2.3
------------------

Ports

 * Our default I/O size (8 MiB) for large files was too large for some
   platforms with smaller SSIZE_MAX, leading to read(2)/write(2)
   failures.

 * We did not check the curl library version before using the
   CURLOPT_PROXYAUTH feature, which did not exist in older versions of
   the library.

 * We now detect number of CPUs on older BSD-derived systems.

 * Portability fixes and workarounds for shell scripts have been added
   to help BSD-derived systems.


UI, Workflows & Features

 * The command usage info strings given by "git cmd -h" and in
   documentation have been tweaked for consistency.

 * The "sync" subcommand of "git p4" now allows users to exclude
   subdirectories like its "clone" subcommand does.

 * "git log --invert-grep --grep=WIP" will show only commits that do
   not have the string "WIP" in their messages.

 * "git push" has been taught an "--atomic" option that makes a push
   that updates more than one ref an "all-or-none" affair.

 * Extending the "push to deploy" feature that was added in 2.3, the
   behaviour of "git push" when updating the branch that is checked
   out can now be tweaked by a "push-to-checkout" hook.

 * HTTP-based transports now send Accept-Language when making
   requests. The languages to accept are inferred from environment
   variables on the client side (LANGUAGE, etc).

 * "git send-email" used to accept a mistaken "y" (or "yes") as an
   answer to "What encoding do you want to use [UTF-8]?" without
   questioning. Now it asks for confirmation when the answer looks too
   short to be a valid encoding name.

 * When "git apply --whitespace=fix" fixed whitespace errors in the
   common context lines, the command reports that it did so.

 * "git status" now allows the "-v" option to be given twice, in which
   case it also shows the differences in the working tree that are not
   staged to be committed.

 * "git cherry-pick" used to clean up the log message even when it is
   merely replaying an existing commit. It now replays the message
   verbatim unless you are editing the message of the resulting
   commit.

 * "git archive" can now be told to set the 'text' attribute in the
   resulting zip archive.

 * Output from "git log --decorate" now distinguishes between a
   detached HEAD vs. a HEAD that points at a branch.

   This is a potentially backward-incompatible change; see above for
   more information.

 * When HEAD was detached when at commit xyz and hasn't been moved
   since it was detached, "git status" would report "detached at xyz"
   whereas "git branch" would report "detached from xyz". Now the
   output of "git branch" agrees with that of "git status".

   This is a potentially backward-incompatible change; see above for
   more information.

 * "git -C '' subcmd" now works in the current directory (analogously
   to "cd ''") rather than dying with an error message.
   (merge 6a536e2 kn/git-cd-to-empty later to maint).

 * The versionsort.prereleaseSuffix configuration variable can be used
   to specify that, for example, v1.0-pre1 comes before v1.0.

 * A new "push.followTags" configuration turns the "--follow-tags"
   option on by default for the "git push" command.

 * "git log --graph --no-walk A B..." is a nonsensical combination of
   options: "--no-walk" requests discrete points in the history, while
   "--graph" asks to draw connections between these discrete points.
   Forbid the use of these options together.

 * "git rev-list --bisect --first-parent" does not work (yet) and can
   even cause SEGV; forbid it. "git log --bisect --first-parent" would
   not be useful until "git bisect --first-parent" materializes, so
   also forbid it for now.


Performance, Internal Implementation, Development Support etc.

 * Slightly change the implementation of the N_() macro to help us
   detect mistakes.

 * Restructure the implementation of "reflog expire" to fit better
   with the recently updated reference API.

 * The transport-helper did not pass transport options such as
   verbosity, progress, cloning, etc. to import and export based
   helpers, like it did for fetch and push based helpers, robbing them
   of the chance to honor the wish of the end-users better.

 * The tests that wanted to see that a file becomes unreadable after
   running "chmod a-r file", and the tests that wanted to make sure
   that they are not run as root, used "can we write into the /
   directory?" as a cheap substitute. But on some platforms that is
   not a good heuristic. The tests and their prerequisites have been
   updated to check what they really require.
   (merge f400e51 jk/sanity later to maint).

 * Various issues around "reflog expire", e.g. using --updateref when
   expiring a reflog for a symbolic reference, have been corrected
   and/or made saner.

 * The documentation for the strbuf API had been split between the API
   documentation and the header file. Consolidate the documentation in
   strbuf.h.

 * The error handling functions and conventions are now documented in
   the API manual (in api-error-handling.txt).

 * Optimize gitattribute look-up, mostly useful in "git grep" on a
   project that does not use many attributes, by avoiding it when we
   (should) know that the attributes are not defined in the first
   place.

 * Typofix in comments.
   (merge ef2956a ak/git-pm-typofix later to maint).

 * Code clean-up.
   (merge 0b868f0 sb/hex-object-name-is-at-most-41-bytes-long later to maint).
   (merge 5d30851 dp/remove-duplicated-header-inclusion later to maint).

 * Simplify the ref transaction API for verifying that "the ref should
   be pointing at this object".

 * Simplify the code in "git daemon" that parses out and holds
   hostnames used in request interpolation.

 * Restructure the "git push" codepath to make it easier to add new
   configuration bits.

 * The run-command interface made it easy to make a pipe for us to
   read from a process, wait for the process to finish, and then
   attempt to read its output. But this pattern can lead to deadlock.
   So introduce a helper to do this correctly (i.e., first read, and
   then wait the process to finish) and also add code to prevent such
   abuse in the run-command helper.

 * People often forget to chain the commands in their test together
   with &&, letting a failure from an earlier command in the test go
   unnoticed. The new GIT_TEST_CHAIN_LINT mechanism allows you to
   catch such a mistake more easily.


Also contains various documentation updates and code clean-ups.


Fixes since v2.3
----------------

Unless otherwise noted, all the fixes since v2.3 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * "git blame HEAD -- missing" failed to correctly say "HEAD" when it
   tried to say "No such path 'missing' in HEAD".
   (merge a46442f jk/blame-commit-label later to maint).

 * "git rerere" (invoked internally from many mergy operations) did
   not correctly signal errors when it attempted to update the working
   tree files but failed for whatever reason.
   (merge 89ea903 jn/rerere-fail-on-auto-update-failure later to maint).

 * Setting diff.submodule to 'log' made "git format-patch" produce
   broken patches.
   (merge 339de50 dk/format-patch-ignore-diff-submodule later to maint).

 * After attempting and failing a password-less authentication (e.g.,
   Kerberos), libcURL refuses to fall back to password-based Basic
   authentication without a bit of help/encouragement.
   (merge 4dbe664 bc/http-fallback-to-password-after-krb-fails later to maint).

 * The "git push" documentation for the "--repo=<there>" option was
   easily misunderstood.
   (merge 57b92a7 mg/push-repo-option-doc later to maint).

 * Code to read a branch name from various files in the .git/
   directory would have overrun array limits if asked to read an empty
   file.
   (merge 66ec904 jk/status-read-branch-name-fix later to maint).

 * Remove a superfluous conditional that is always true.
   (merge 94ee8e2 jk/remote-curl-an-array-in-struct-cannot-be-null later to maint).

 * The "git diff --raw" documentation incorrectly implied that C(opy)
   and R(ename) are the only statuses that can be followed by a score
   number.
   (merge ac1c2d9 jc/diff-format-doc later to maint).

 * A broken pack .idx file in the receiving repository prevented the
   dumb http transport from fetching a good copy of it from the other
   side.
   (merge 8b9c2dd jk/dumb-http-idx-fetch-fix later to maint).

 * The error message from "git commit", when a non-existing author
   name was given as value to the "--author=" parameter, has been
   reworded to avoid misunderstanding.
   (merge 1044b1f mg/commit-author-no-match-malformed-message later to maint).

 * "git log --help" used to show rev-list options that are irrelevant
   to the "log" command.
   (merge 3cab02d jc/doc-log-rev-list-options later to maint).

 * "git apply --whitespace=fix" used to under-allocate memory when the
   fix resulted in a longer text than the original patch.
   (merge 407a792 jc/apply-ws-fix-expands later to maint).

 * The interactive "show a list and let the user choose from it"
   interface used by "git add -i" unnecessarily prompted the user even
   when the candidate list was empty, against which the only "choice"
   the user could have made was to choose nothing.
   (merge a9c4641 ak/add-i-empty-candidates later to maint).

 * The todo list created by "git rebase -i" did not fully honor
   core.abbrev settings.
   (merge edb72d5 ks/rebase-i-abbrev later to maint).

 * "git fetch" over a remote-helper that cannot respond to the "list"
   command could not fetch from a symbolic reference (e.g., HEAD).
   (merge 33cae54 mh/deref-symref-over-helper-transport later to maint).

 * "git push --signed" gave an incorrectly worded error message when
   the other side did not support the capability.

 * The "git push --signed" protocol extension did not limit what the
   "nonce" (a server-chosen string) could contain nor how long it
   could be, which was unnecessarily lax. Limit both the length and
   the alphabet to a reasonably small space that can still have enough
   entropy.
   (merge afcb6ee jc/push-cert later to maint).

 * The completion script (in contrib/) clobbered the shell variable $x
   in the global shell namespace.
   (merge 852ff1c ma/bash-completion-leaking-x later to maint).

 * We incorrectly formatted a "uintmax_t" integer that doesn't fit in
   "int".
   (merge d306f3d jk/decimal-width-for-uintmax later to maint).

 * The configuration parser used to be confused when reading
   configuration from a blob object that ends with a lone CR.
   (merge 1d0655c jk/config-no-ungetc-eof later to maint).

 * The pack bitmap support did not build with older versions of GCC.
   (merge bd4e882 jk/pack-bitmap later to maint).

 * The documentation wasn't clear that "remote.<nick>.pushURL" and
   "remote.<nick>.URL" are there to name the same repository accessed
   via different transports, not two separate repositories.
   (merge 697f652 jc/remote-set-url-doc later to maint).

 * Older GnuPG implementations may not correctly import the keyring
   material we prepare for the tests to use.
   (merge 1f985d6 ch/new-gpg-drops-rfc-1991 later to maint).

 * The credential helper for Windows (in contrib/) used to mishandle
   user names that contain an at-sign.
   (merge 13d261e av/wincred-with-at-in-username-fix later to maint).

 * "diff-highlight" (in contrib/) used to show byte-by-byte
   differences, which could cause multi-byte characters to be chopped
   in the middle. It learned to pay attention to character boundaries
   (assuming UTF-8).
   (merge 8d00662 jk/colors later to maint).

 * Document longstanding configuration variable naming rules in
   CodingGuidelines.
   (merge 35840a3 jc/conf-var-doc later to maint).

 * An earlier workaround to squelch unhelpful deprecation warnings
   from the compiler on OS X unnecessarily set a minimum required
   version of the OS, which the user might want to raise (or lower)
   for other reasons.
   (merge 88c03eb es/squelch-openssl-warnings-on-macosx later to maint).

 * Certain older vintages of cURL give irregular output from
   "curl-config --vernum", which confused our build system.
   (merge 3af6792 tc/curl-vernum-output-broken-in-7.11 later to maint).

 * In v2.2.0, we broke "git prune" that runs in a repository that
   borrows from an alternate object store.
   (merge b0a4264 jk/prune-mtime later to maint).

 * "git submodule add" failed to squash "path/to/././submodule" to
   "path/to/submodule".
   (merge 8196e72 ps/submodule-sanitize-path-upon-add later to maint).

 * "git merge-file" did not work correctly when invoked in a
   subdirectory.
   (merge 204a8ff ab/merge-file-prefix later to maint).

 * "git blame" could die trying to free an uninitialized piece of
   memory.
   (merge e600592 es/blame-commit-info-fix later to maint).

 * "git fast-import" used to crash when it could not close and
   finalize the resulting packfile cleanly.
   (merge 5e915f3 jk/fast-import-die-nicely-fix later to maint).

 * "update-index --refresh" used to leak memory when an entry could
   not be refreshed for whatever reason.
   (merge bc1c2ca sb/plug-leak-in-make-cache-entry later to maint).

 * The "interpolated-path" option of "git daemon" inserted any string
   the client declared on the "host=" capability request without
   checking. Sanitize and limit %H and %CH to a saner and a valid DNS
   name.
   (merge b485373 jk/daemon-interpolate later to maint).

 * "git daemon" unnecessarily looked up the hostname even when "%CH"
   and "%IP" interpolations were not requested.
   (merge dc8edc8 rs/daemon-interpolate later to maint).

 * We relied on "--no-" prefix handling in Perl's Getopt::Long
   package, even though that support didn't exist in Perl 5.8 (which
   we still support). Manually add support to help people with older
   Getopt::Long packages.
   (merge f471494 km/send-email-getopt-long-workarounds later to maint).

 * "git apply" was not very careful about reading from, removing,
   updating and creating paths outside the working tree (under
   --index/--cached) or the current directory (when used as a
   replacement for GNU patch).
   (merge e0d201b jc/apply-beyond-symlink later to maint).

 * Correct a breakage in git-svn, introduced around the v2.2 era, that
   can cause FileHandles to be closed prematurely.
   (merge e426311 ew/svn-maint-fixes later to maint).

 * We did not parse usernames followed by literal IPv6 addresses
   correctly in SSH transport URLs; e.g.,
   ssh://user@[2001:db8::1]:22/repo.git.
   (merge 6b6c5f7 tb/connect-ipv6-parse-fix later to maint).

 * The configuration variable 'mailinfo.scissors' was hard to
   discover in the documentation.
   (merge afb5de7 mm/am-c-doc later to maint).

 * The interaction between "git submodule update" and the
   submodule.*.update configuration was not clearly documented.
   (merge 5c31acf ms/submodule-update-config-doc later to maint).

 * "git diff --shortstat" used together with "--dirstat=changes" or
   "--dirstat=files" incorrectly output dirstat information twice.
   (merge ab27389 mk/diff-shortstat-dirstat-fix later to maint).

 * The manpage for "git remote add" mentioned "--tags" and "--no-tags"
   but did not explain what happens if neither option is provided.
   (merge aaba0ab mg/doc-remote-tags-or-not later to maint).

 * The description of "--exclude-standard option" in the output of
   "git grep -h" was phrased poorly.
   (merge 77fdb8a nd/grep-exclude-standard-help-fix later to maint).

 * "git rebase -i" recently started to include the number of commits
   in the todo list, but that output included extraneous whitespace on
   a platform that prepends leading whitespaces to its "wc -l" output.
   (merge 2185d3b es/rebase-i-count-todo later to maint).

 * The borrowed code in the kwset API did not follow our usual
   convention to use "unsigned char" to store values that range from
   0-255.
   (merge 189c860 bw/kwset-use-unsigned later to maint).

 * A corrupt input to "git diff -M" used to cause it to segfault.
   (merge 4d6be03 jk/diffcore-rename-duplicate later to maint).

 * Certain builds of GPG triggered false breakages in a test.
   (merge 3f88c1b mg/verify-commit later to maint).

 * "git imap-send" learned to optionally talk with an IMAP server via
   libcURL. Because there is no other option when Git is built with
   the NO_OPENSSL option, use libcURL by default in that case.
   (merge dcd01ea km/imap-send-libcurl-options later to maint).

 * "git log --decorate" did not reset colors correctly around the
   branch names.
   (merge 5ee8758 jc/decorate-leaky-separator-color later to maint).

 * The code that reads from the ctags file in the completion script
   (in contrib/) did not spell ${param/pattern/string} substitution
   correctly, which happened to work with bash but not with zsh.
   (merge db8d750 js/completion-ctags-pattern-substitution-fix later to maint).

 * The transfer.hiderefs support did not quite work for smart-http
   transport.
   (merge 8ddf3ca jk/smart-http-hide-refs later to maint).

 * In the "git tag -h" output, move the documentation for the
   "--column" and "--sort" options to the "Tag listing options"
   section.
   (merge dd059c6 jk/tag-h-column-is-a-listing-option later to maint).

 * "git prune" used to largely ignore broken refs when deciding which
   objects are still being used, which could cause reference
   corruption to lead to object loss.
   (merge ea56c4e jk/prune-with-corrupt-refs later to maint).

 * The split-index mode introduced in v2.3.0-rc0~41 was broken in the
   codepath to protect us against a broken reimplementation of Git
   that writes an invalid index with duplicated index entries, etc.
   (merge 03f15a7 tg/fix-check-order-with-split-index later to maint).

 * "git fetch", when fetching a commit using the
   allow-tip-sha1-in-want extension, could have failed to fetch all of
   the requested refs.
   (merge 32d0462 jk/fetch-pack later to maint).

 * An failure early in the "git clone" that started creating the
   working tree and repository could have resulted in the failure to
   clean up some directories and files.
   (merge 16eff6c jk/cleanup-failed-clone later to maint).

 * Recommend format-patch and send-email for those who want to submit
   patches to this project.
   (merge b25c469 jc/submitting-patches-mention-send-email later to maint).

 * Do not spawn the pager when "git grep" is run with "--quiet".
   (merge c2048f0 ws/grep-quiet-no-pager later to maint).

 * The prompt script (in contrib/) did not show the untracked sign
   when working in a subdirectory without any untracked files.
   (merge 9bdc517 ct/prompt-untracked-fix later to maint).

 * An earlier update to the URL parser broke an address that contains
   a colon but an empty string for the port number, like
   ssh://example.com:/path/to/repo.
   (merge 6b6c5f7 tb/connect-ipv6-parse-fix later to maint).

 * Code cleanups and documentation updates.
   (merge 2ce63e9 rs/simple-cleanups later to maint).
   (merge 33baa69 rj/no-xopen-source-for-cygwin later to maint).
   (merge 817d03e jc/diff-test-updates later to maint).
   (merge eb32c66 ak/t5516-typofix later to maint).
   (merge bcd57cb mr/doc-clean-f-f later to maint).
   (merge 0d6accc mg/doc-status-color-slot later to maint).
   (merge 53e53c7 sg/completion-remote later to maint).
   (merge 8fa7975 ak/git-done-help-cleanup later to maint).
   (merge 9a6f128 rs/deflate-init-cleanup later to maint).
   (merge 6f75d45 rs/use-isxdigit later to maint).
   (merge 376e4b3 jk/test-annoyances later to maint).
   (merge 7032054 nd/doc-git-index-version later to maint).
   (merge e869c5e tg/test-index-v4 later to maint).
   (merge 599d223 jk/simplify-csum-file-sha1fd-check later to maint).
   (merge 260d585 sg/completion-gitcomp-nl-for-refs later to maint).
   (merge 777c55a jc/report-path-error-to-dir later to maint).
   (merge fddfaf8 ph/push-doc-cas later to maint).
   (merge d50d31e ss/pull-rebase-preserve later to maint).
   (merge c8c3f1d pt/enter-repo-comment-fix later to maint).
   (merge d7bfb9e jz/gitweb-conf-doc-fix later to maint).
   (merge f907282 jk/cherry-pick-docfix later to maint).
   (merge d3c0811 iu/fix-parse-options-h-comment later to maint).
   (merge 6c3b2af jg/cguide-we-cannot-count later to maint).
   (merge 2b8bd44 jk/pack-corruption-post-mortem later to maint).
   (merge 9585cb8 jn/doc-fast-import-no-16-octopus-limit later to maint).
   (merge 5dcd1b1 ps/grep-help-all-callback-arg later to maint).
   (merge f1f4c84 va/fix-git-p4-tests later to maint).

^ permalink raw reply	[relevance 2%]

* Re: Patch that modifies git usage message
  @ 2015-05-01 16:55  4%     ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-01 16:55 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Alangi Derick, git@vger.kernel.org

On Fri, May 1, 2015 at 9:29 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> For the patch itself:
>>
>> $ grep -r usage *.c builtin/*.c |wc -l
>> 551
>> $ grep -r Usage *.c builtin/*.c |wc -l
>> 3
>>
>> The community agreed (maybe subconciously) to prefer lower case
>> for the 'usage' string, so I don't think this is an improvement.
>
> I tend to agree with the conclusion, but you need to be a bit
> careful here.  These catch all the variable names that contain
> "[uU]sage" as substring, but we do not spell in-code variables
> with camelCase, so the former probably is over-counting.  Things
> like "static const char usage[] = ..." are counted; so are calls
> to usage_with_options().

I knew my search was off as I did not think it through, but I
just wanted to have at least some data to not be hand waving only
here.

Maybe we can also rely on the colon in this case:
$ grep -r "usage:" *.{c,sh,perl}
finds 22 results, 21 thereof look like human readable usage instructions
$ grep -r "Usage:" *.{c,sh,perl}
finds 2 results which look like human readable text

>
> If you look for the beginning of a string constant, you would get
> this:
>
>     $ git grep '"usage' -- \*.c builtin/\*.c
>     12
>     $ git grep '"Usage' -- \*.c builtin/\*.c
>     0
>
> The former undercounts the messages because many usage messages are
> produced by calling usage_with_options() these days.
>
> The latter being zero made me scratch my head and do this:
>
>     $ git grep Usage -- \*.c builtin/\*.c
>     commit.c: * Usage example:
>     test-hashmap.c: * Usage: time echo "perfhas...
>
> I cannot find the third one you found for "Usage" in your example,
> though.

test-submodule-config.c: fprintf(stderr, "Usage: %s [<commit>
<submodulepath>] ...\n", argv[0]);
(I just realize HEAD wa pointing somewhere in pu)

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] fixed translation errors
  @ 2015-05-04 17:39  2% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-04 17:39 UTC (permalink / raw)
  To: Alangi Derick, git@vger.kernel.org

On Sun, May 3, 2015 at 3:19 PM, Alangi Derick <alangiderick@gmail.com> wrote:
> Signed-off-by: Alangi Derick <alangiderick@gmail.com>
> ---
>  builtin/apply.c | 60 ++++++++++++++++++++++++++++-----------------------------
>  1 file changed, 30 insertions(+), 30 deletions(-)
>
> diff --git a/builtin/apply.c b/builtin/apply.c
> index 0769b09..66d2aba 100644
> --- a/builtin/apply.c
> +++ b/builtin/apply.c

Please have a look at command-list.txt
or the entry man page of git [1], which makes
a difference between plumbing commands and
porcelain commands.

The plumbing layer is intended for use in scripts.
And looking for error messages in scripts is quite un easy
if these are actually translated.

The porcelain layer, which is intended to be used by people,
should have all the translations, because humans do like to
see the error message in their configured language.

[1] https://www.kernel.org/pub/software/scm/git/docs/

> @@ -1381,7 +1381,7 @@ static void recount_diff(const char *line, int size, struct fragment *fragment)
>         int oldlines = 0, newlines = 0, ret = 0;
>
>         if (size < 1) {
> -               warning("recount: ignore empty hunk");
> +               warning(_("recount: ignore empty hunk"));
>                 return;
>         }
>
> @@ -1500,8 +1500,8 @@ static int find_header(const char *line, unsigned long size, int *hdrsize, struc
>                                 patch->new_name = xstrdup(patch->def_name);
>                         }
>                         if (!patch->is_delete && !patch->new_name)
> -                               die("git diff header lacks filename information "
> -                                   "(line %d)", linenr);
> +                               die(_("git diff header lacks filename information "
> +                                   "(line %d)"), linenr);
>                         patch->is_toplevel_relative = 1;
>                         *hdrsize = git_hdr_len;
>                         return offset;
> @@ -2237,7 +2237,7 @@ static void update_pre_post_images(struct image *preimage,
>         if (postlen
>             ? postlen < new - postimage->buf
>             : postimage->len < new - postimage->buf)
> -               die("BUG: caller miscounted postlen: asked %d, orig = %d, used = %d",
> +               die(_("BUG: caller miscounted postlen: asked %d, orig = %d, used = %d"),
>                     (int)postlen, (int) postimage->len, (int)(new - postimage->buf));
>
>         /* Fix the length of the whole thing */
> @@ -2940,8 +2940,8 @@ static int apply_binary_fragment(struct image *img, struct patch *patch)
>         /* Binary patch is irreversible without the optional second hunk */
>         if (apply_in_reverse) {
>                 if (!fragment->next)
> -                       return error("cannot reverse-apply a binary patch "
> -                                    "without the reverse hunk to '%s'",
> +                       return error(_("cannot reverse-apply a binary patch "
> +                                    "without the reverse hunk to '%s'"),
>                                      patch->new_name
>                                      ? patch->new_name : patch->old_name);
>                 fragment = fragment->next;
> @@ -2984,8 +2984,8 @@ static int apply_binary(struct image *img, struct patch *patch)
>             strlen(patch->new_sha1_prefix) != 40 ||
>             get_sha1_hex(patch->old_sha1_prefix, sha1) ||
>             get_sha1_hex(patch->new_sha1_prefix, sha1))
> -               return error("cannot apply binary patch to '%s' "
> -                            "without full index line", name);
> +               return error(_("cannot apply binary patch to '%s' "
> +                            "without full index line"), name);
>
>         if (patch->old_name) {
>                 /*
> @@ -2994,16 +2994,16 @@ static int apply_binary(struct image *img, struct patch *patch)
>                  */
>                 hash_sha1_file(img->buf, img->len, blob_type, sha1);
>                 if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix))
> -                       return error("the patch applies to '%s' (%s), "
> +                       return error(_("the patch applies to '%s' (%s), "
>                                      "which does not match the "
> -                                    "current contents.",
> +                                    "current contents."),
>                                      name, sha1_to_hex(sha1));
>         }
>         else {
>                 /* Otherwise, the old one must be empty. */
>                 if (img->len)
> -                       return error("the patch applies to an empty "
> -                                    "'%s' but it is not empty", name);
> +                       return error(_("the patch applies to an empty "
> +                                    "'%s' but it is not empty"), name);
>         }
>
>         get_sha1_hex(patch->new_sha1_prefix, sha1);
> @@ -3020,8 +3020,8 @@ static int apply_binary(struct image *img, struct patch *patch)
>
>                 result = read_sha1_file(sha1, &type, &size);
>                 if (!result)
> -                       return error("the necessary postimage %s for "
> -                                    "'%s' cannot be read",
> +                       return error(_("the necessary postimage %s for "
> +                                    "'%s' cannot be read"),
>                                      patch->new_sha1_prefix, name);
>                 clear_image(img);
>                 img->buf = result;
> @@ -3342,7 +3342,7 @@ static int load_current(struct image *image, struct patch *patch)
>         unsigned mode = patch->new_mode;
>
>         if (!patch->is_new)
> -               die("BUG: patch to %s is not a creation", patch->old_name);
> +               die(_("BUG: patch to %s is not a creation"), patch->old_name);
>
>         pos = cache_name_pos(name, strlen(name));
>         if (pos < 0)
> @@ -3387,7 +3387,7 @@ static int try_threeway(struct image *image, struct patch *patch,
>                 write_sha1_file("", 0, blob_type, pre_sha1);
>         else if (get_sha1(patch->old_sha1_prefix, pre_sha1) ||
>                  read_blob_object(&buf, pre_sha1, patch->old_mode))
> -               return error("repository lacks the necessary blob to fall back on 3-way merge.");
> +               return error(_("repository lacks the necessary blob to fall back on 3-way merge."));
>
>         fprintf(stderr, "Falling back to three-way merge...\n");
>
> @@ -3405,11 +3405,11 @@ static int try_threeway(struct image *image, struct patch *patch,
>         /* our_sha1[] is ours */
>         if (patch->is_new) {
>                 if (load_current(&tmp_image, patch))
> -                       return error("cannot read the current contents of '%s'",
> +                       return error(_("cannot read the current contents of '%s'"),
>                                      patch->new_name);
>         } else {
>                 if (load_preimage(&tmp_image, patch, st, ce))
> -                       return error("cannot read the current contents of '%s'",
> +                       return error(_("cannot read the current contents of '%s'"),
>                                      patch->old_name);
>         }
>         write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, our_sha1);
> @@ -3572,7 +3572,7 @@ static int check_to_create(const char *new_name, int ok_if_exists)
>
>                 return EXISTS_IN_WORKTREE;
>         } else if ((errno != ENOENT) && (errno != ENOTDIR)) {
> -               return error("%s: %s", new_name, strerror(errno));
> +               return error(_("%s: %s"), new_name, strerror(errno));
>         }
>         return 0;
>  }
> @@ -3888,29 +3888,29 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
>                         if (!preimage_sha1_in_gitlink_patch(patch, sha1))
>                                 ; /* ok, the textual part looks sane */
>                         else
> -                               die("sha1 information is lacking or useless for submodule %s",
> +                               die(_("sha1 information is lacking or useless for submodule %s"),
>                                     name);
>                 } else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
>                         ; /* ok */
>                 } else if (!patch->lines_added && !patch->lines_deleted) {
>                         /* mode-only change: update the current */
>                         if (get_current_sha1(patch->old_name, sha1))
> -                               die("mode change for %s, which is not "
> -                                   "in current HEAD", name);
> +                               die(_("mode change for %s, which is not "
> +                                   "in current HEAD"), name);
>                 } else
> -                       die("sha1 information is lacking or useless "
> -                           "(%s).", name);
> +                       die(_("sha1 information is lacking or useless "
> +                           "(%s)."), name);
>
>                 ce = make_cache_entry(patch->old_mode, sha1, name, 0, 0);
>                 if (!ce)
>                         die(_("make_cache_entry failed for path '%s'"), name);
>                 if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
> -                       die ("Could not add %s to temporary index", name);
> +                       die(_("Could not add %s to temporary index"), name);
>         }
>
>         hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
>         if (write_locked_index(&result, &lock, COMMIT_LOCK))
> -               die ("Could not write temporary index to %s", filename);
> +               die(_("Could not write temporary index to %s"), filename);
>
>         discard_index(&result);
>  }
> @@ -4599,9 +4599,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
>                         apply_usage, 0);
>
>         if (apply_with_reject && threeway)
> -               die("--reject and --3way cannot be used together.");
> +               die(("--reject and --3way cannot be used together."));
>         if (cached && threeway)
> -               die("--cached and --3way cannot be used together.");
> +               die(("--cached and --3way cannot be used together."));
>         if (threeway) {
>                 if (is_not_gitdir)
>                         die(_("--3way outside a repository"));
> @@ -4659,8 +4659,8 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
>                                whitespace_error),
>                             whitespace_error);
>                 if (applied_after_fixing_ws && apply)
> -                       warning("%d line%s applied after"
> -                               " fixing whitespace errors.",
> +                       warning(_("%d line%s applied after"
> +                               " fixing whitespace errors."),
>                                 applied_after_fixing_ws,
>                                 applied_after_fixing_ws == 1 ? "" : "s");
>                 else if (whitespace_error)
> --
> 2.4.0.2.g3386abe.dirty
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 2%]

* Re: [PATCH 11/14] pull: teach git pull about --rebase
  @ 2015-05-18 23:36  2%   ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-18 23:36 UTC (permalink / raw)
  To: Paul Tan; +Cc: git@vger.kernel.org, Johannes Schindelin, Stephen Robin

On Mon, May 18, 2015 at 8:06 AM, Paul Tan <pyokagan@gmail.com> wrote:

> +enum rebase_type {
> +       REBASE_FALSE,
> +       REBASE_TRUE,
> +       REBASE_PRESERVE
> +};
> +
> +/**
> + * Parses the value of --rebase, branch.*.rebase or pull.rebase. If value is a
> + * false value, returns REBASE_FALSE. If value is a true value, returns
> + * REBASE_TRUE. If value is "preserve", returns REBASE_PRESERVE. Otherwise,
> + * returns -1 to signify an invalid value.
> + */
> +static int parse_config_rebase(const char *value)
> +{
> +       int v = git_config_maybe_bool("pull.rebase", value);
> +       if (v >= 0)
> +               return v;
> +       if (!strcmp(value, "preserve"))
> +               return REBASE_PRESERVE;
> +       return -1;

There is no REBASE_FALSE nor REBASE_TRUE in this function,
how do you make sure it returns the correct value then?

Currently this is probably in sync with what git_config_maybe_bool
returns, but think of a future refactoring/change. Then it will be hard
to have the connection between what the code in git_config_maybe_bool
does, what the code here does and the comment here.

You could get rid of the enum all together, as you're using integer as a
return type anyway. (so you lose type safety, a future change may introduce
a "return 42" which is not part of the enum)

Or you could convert the code to use the enum more strictly and having it
as the return type:

enum rebase_type parse_config_rebase(const char *value) {
    int v = git_config_maybe_bool("pull.rebase", value);
    switch (v) {
        case 0:
            return REBASE_FALSE;
        case 1:
            return REBASE_TRUE;
        default:
             if (!strcmp(value, "preserve"))
                return  REBASE_PRESERVE;
             else {
                die("value pull.rebase must be one of {false, true, preserve}");
                // or if you're more tolerant:
                return REBASE_VALUE_UNINTERPRETABLE;
       }
   }


> +}
> +
> +/**
> + * Callback for --rebase, which parses arg with parse_config_rebase().
> + */
> +static int parse_opt_rebase(const struct option *opt, const char *arg, int unset)
> +{
> +       int *value = (int*) opt->value;
> +
> +       if (arg)
> +               *value = parse_config_rebase(arg);
> +       else
> +               *value = unset ? REBASE_FALSE : REBASE_TRUE;
> +       return *value >= 0 ? 0 : -1;

This is repeating the check from above. If you'd go the way of using
stricter enums,
you'd just check for the REBASE_VALUE_UNINTERPRETABLE
value here.

> +}
> +
>  static const char * const pull_usage[] = {
>         N_("git pull [options] [<repo> [<refspec>...]]"),
>         NULL
> @@ -48,7 +84,8 @@ static const char * const pull_usage[] = {
>  static int opt_verbosity;
>  static char *opt_progress;
>
> -/* Options passed to git-merge */
> +/* Options passed to git-merge or git-rebase */
> +static int opt_rebase;
>  static char *opt_diffstat;
>  static char *opt_log;
>  static char *opt_squash;
> @@ -82,8 +119,12 @@ static struct option pull_options[] = {
>           N_("force progress reporting"),
>           PARSE_OPT_NOARG, parse_opt_passthru},
>
> -       /* Options passed to git-merge */
> +       /* Options passed to git-merge or git-rebase */
>         OPT_GROUP(N_("Options related to merging")),
> +       { OPTION_CALLBACK, 'r', "rebase", &opt_rebase,
> +         N_("false|true|preserve"),
> +         N_("incorporate changes by rebasing rather than merging"),
> +         PARSE_OPT_OPTARG, parse_opt_rebase, 0},
>         { OPTION_CALLBACK, 'n', NULL, &opt_diffstat, NULL,
>           N_("do not show a diffstat at the end of the merge"),
>           PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_passthru, (intptr_t) "no-stat" },
> @@ -506,11 +547,185 @@ static int run_merge(void)
>         return ret;
>  }
>
> +/**
> + * Returns the merge branch for the current branch. Returns NULL if repo is not
> + * a valid remote, HEAD does not point to a branch, repo is not the branch's
> + * configured remote or the branch does not have any configured merge branch.
> + */
> +static char *get_merge_branch_1(const char *repo)
> +{
> +       struct remote *rm;
> +       struct branch *curr_branch;
> +
> +       if (repo && !(rm = remote_get(repo)))
> +               return NULL;
> +       if (!(curr_branch = branch_get("HEAD")))
> +               return NULL;
> +       if (repo && curr_branch->remote != rm)
> +               return NULL;
> +       if (!curr_branch->merge_nr)
> +               return NULL;
> +       return xstrdup(curr_branch->merge[0]->dst);
> +}

This feels a bit tangled because of the repetition of checking
for repo and curr_branch. Also we do not do assignments inside
of conditions (if, while, for), so maybe start with a

    if (!repo)
        return NULL;

and then do the assignments and test on the assigned value.

> +
> +/**
> + * Given a refspec, returns the merge branch. Returns NULL if the refspec src
> + * does not refer to a branch.
> + *
> + * FIXME: It should return the tracking branch. Currently only works with the
> + * default mapping.
> + */
> +static char *get_merge_branch_2(const char *repo, const char *refspec)
> +{
> +       struct refspec *spec;
> +       const char *remote;
> +       char *merge_branch;
> +
> +       spec = parse_fetch_refspec(1, &refspec);
> +       remote = spec->src;
> +       if (!*remote || !strcmp(remote, "HEAD"))
> +               remote = "HEAD";
> +       else if (skip_prefix(remote, "heads/", &remote))
> +               ;
> +       else if (skip_prefix(remote, "refs/heads/", &remote))
> +               ;
> +       else if (starts_with(remote, "refs/") ||
> +               starts_with(remote, "tags/") ||
> +               starts_with(remote, "remotes/"))
> +               remote = "";
> +
> +       if (*remote) {
> +               if (!strcmp(repo, "."))
> +                       merge_branch = mkpathdup("refs/heads/%s", remote);
> +               else
> +                       merge_branch = mkpathdup("refs/remotes/%s/%s", repo, remote);
> +       } else
> +               merge_branch = NULL;
> +
> +       free_refspec(1, spec);
> +       return merge_branch;
> +}
> +
> +/**
> + * Sets fork_point to the point at which the current branch forked from its
> + * remote merge branch. Returns 0 on success, -1 on failure.
> + */
> +static int get_rebase_fork_point(unsigned char fork_point[GIT_SHA1_RAWSZ],
> +               const char *repo, const char *refspec)
> +{
> +       int ret;
> +       struct branch *curr_branch;
> +       char *remote_merge_branch;
> +       struct argv_array args = ARGV_ARRAY_INIT;
> +       struct child_process cp = CHILD_PROCESS_INIT;
> +       struct strbuf sb = STRBUF_INIT;
> +
> +       if (!(curr_branch = branch_get("HEAD")))
> +               return -1;
> +
> +       if (refspec)
> +               remote_merge_branch = get_merge_branch_2(repo, refspec);
> +       else
> +               remote_merge_branch = get_merge_branch_1(repo);
> +
> +       if (!remote_merge_branch)
> +               return -1;
> +
> +       argv_array_pushl(&args, "merge-base", "--fork-point",
> +                       remote_merge_branch, curr_branch->name, NULL);
> +       cp.argv = args.argv;
> +       cp.no_stdin = 1;
> +       cp.no_stderr = 1;
> +       cp.git_cmd = 1;
> +
> +       if ((ret = capture_command(&cp, &sb, GIT_SHA1_HEXSZ)))
> +               goto cleanup;
> +
> +       if ((ret = get_sha1_hex(sb.buf, fork_point)))
> +               goto cleanup;
> +
> +cleanup:
> +       free(remote_merge_branch);
> +       strbuf_release(&sb);
> +       return ret ? -1 : 0;
> +}
> +
> +/**
> + * Sets merge_base to the octopus merge base of curr_head, merge_head and
> + * fork_point. Returns 0 if a merge base is found, 1 otherwise.
> + */
> +static int get_octopus_merge_base(unsigned char merge_base[GIT_SHA1_HEXSZ],
> +               unsigned char curr_head[GIT_SHA1_RAWSZ],
> +               unsigned char merge_head[GIT_SHA1_RAWSZ],
> +               unsigned char fork_point[GIT_SHA1_RAWSZ])
> +{
> +       struct commit_list *revs = NULL, *result;
> +
> +       commit_list_insert(lookup_commit_reference(curr_head), &revs);
> +       commit_list_insert(lookup_commit_reference(merge_head), &revs);
> +       if (!is_null_sha1(fork_point))
> +               commit_list_insert(lookup_commit_reference(fork_point), &revs);
> +
> +       result = reduce_heads(get_octopus_merge_bases(revs));
> +       free_commit_list(revs);
> +       if (!result)
> +               return 1;
> +
> +       hashcpy(merge_base, result->item->object.sha1);
> +       return 0;
> +}
> +
> +/**
> + * Given the current HEAD SHA1, the merge head returned from git-fetch and the
> + * fork point calculated by get_rebase_fork_point(), runs git-rebase with the
> + * appropriate arguments and returns its exit status.
> + */
> +static int run_rebase(unsigned char curr_head[GIT_SHA1_RAWSZ],
> +               unsigned char merge_head[GIT_SHA1_RAWSZ],
> +               unsigned char fork_point[GIT_SHA1_RAWSZ])
> +{
> +       int ret;
> +       unsigned char oct_merge_base[GIT_SHA1_RAWSZ];
> +       struct argv_array args = ARGV_ARRAY_INIT;
> +
> +       if (!get_octopus_merge_base(oct_merge_base, curr_head, merge_head, fork_point))
> +               if (!is_null_sha1(fork_point) && !hashcmp(oct_merge_base, fork_point))
> +                       hashclr(fork_point);
> +
> +       argv_array_push(&args, "rebase");
> +
> +       /* Shared options */
> +       argv_push_verbosity(&args);
> +
> +       /* Options passed to git-rebase */
> +       if (opt_rebase == REBASE_PRESERVE)
> +               argv_array_push(&args, "--preserve-merges");
> +       if (opt_diffstat)
> +               argv_array_push(&args, opt_diffstat);
> +       argv_push_strategies(&args);
> +       argv_push_strategy_opts(&args);
> +       if (opt_gpg_sign)
> +               argv_array_push(&args, opt_gpg_sign);
> +
> +       argv_array_push(&args, "--onto");
> +       argv_array_push(&args, sha1_to_hex(merge_head));
> +
> +       if (!is_null_sha1(fork_point))
> +               argv_array_push(&args, sha1_to_hex(fork_point));
> +       else
> +               argv_array_push(&args, sha1_to_hex(merge_head));
> +
> +       ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
> +       argv_array_clear(&args);
> +       return ret;
> +}
> +
>  int cmd_pull(int argc, const char **argv, const char *prefix)
>  {
>         const char *repo, **refspecs;
>         struct sha1_array merge_heads = SHA1_ARRAY_INIT;
>         unsigned char orig_head[GIT_SHA1_RAWSZ], curr_head[GIT_SHA1_RAWSZ];
> +       unsigned char rebase_fork_point[GIT_SHA1_RAWSZ];
>
>         if (!getenv("GIT_REFLOG_ACTION"))
>                 set_reflog_message(argc, argv);
> @@ -532,6 +747,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
>         if (get_sha1("HEAD", orig_head))
>                 hashclr(orig_head);
>
> +       if (opt_rebase)
> +               if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))
> +                       hashclr(rebase_fork_point);
> +
>         if (run_fetch(repo, refspecs))
>                 return 1;
>
> @@ -573,6 +792,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
>                 if (merge_heads.nr > 1)
>                         die(_("Cannot merge multiple branches into empty head."));
>                 return pull_into_void(*merge_heads.sha1, curr_head);
> +       } else if (opt_rebase) {
> +               if (merge_heads.nr > 1)
> +                       die(_("Cannot rebase onto multiple branches."));
> +               return run_rebase(curr_head, *merge_heads.sha1, rebase_fork_point);
>         } else
>                 return run_merge();
>  }
> diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
> index 9414cc1..3798b96 100755
> --- a/t/t5520-pull.sh
> +++ b/t/t5520-pull.sh
> @@ -212,7 +212,7 @@ test_expect_success 'fast-forward fails with conflicting work tree' '
>         test "$(git rev-parse third)" = "$(git rev-parse second)"
>  '
>
> -test_expect_failure '--rebase' '
> +test_expect_success '--rebase' '
>         git branch to-rebase &&
>         echo modified again > file &&
>         git commit -m file file &&
> @@ -226,7 +226,7 @@ test_expect_failure '--rebase' '
>         test new = "$(git show HEAD:file2)"
>  '
>
> -test_expect_failure '--rebase fails with multiple branches' '
> +test_expect_success '--rebase fails with multiple branches' '
>         git reset --hard before-rebase &&
>         test_must_fail git pull --rebase . copy master 2>err &&
>         test "$(git rev-parse HEAD)" = "$(git rev-parse before-rebase)" &&
> @@ -310,7 +310,7 @@ test_expect_failure 'pull.rebase=invalid fails' '
>         ! git pull . copy
>  '
>
> -test_expect_failure '--rebase=false create a new merge commit' '
> +test_expect_success '--rebase=false create a new merge commit' '
>         git reset --hard before-preserve-rebase &&
>         test_config pull.rebase true &&
>         git pull --rebase=false . copy &&
> @@ -319,7 +319,7 @@ test_expect_failure '--rebase=false create a new merge commit' '
>         test file3 = "$(git show HEAD:file3.t)"
>  '
>
> -test_expect_failure '--rebase=true rebases and flattens keep-merge' '
> +test_expect_success '--rebase=true rebases and flattens keep-merge' '
>         git reset --hard before-preserve-rebase &&
>         test_config pull.rebase preserve &&
>         git pull --rebase=true . copy &&
> @@ -327,7 +327,7 @@ test_expect_failure '--rebase=true rebases and flattens keep-merge' '
>         test file3 = "$(git show HEAD:file3.t)"
>  '
>
> -test_expect_failure '--rebase=preserve rebases and merges keep-merge' '
> +test_expect_success '--rebase=preserve rebases and merges keep-merge' '
>         git reset --hard before-preserve-rebase &&
>         test_config pull.rebase true &&
>         git pull --rebase=preserve . copy &&
> @@ -340,7 +340,7 @@ test_expect_success '--rebase=invalid fails' '
>         ! git pull --rebase=invalid . copy
>  '
>
> -test_expect_failure '--rebase overrides pull.rebase=preserve and flattens keep-merge' '
> +test_expect_success '--rebase overrides pull.rebase=preserve and flattens keep-merge' '
>         git reset --hard before-preserve-rebase &&
>         test_config pull.rebase preserve &&
>         git pull --rebase . copy &&
> @@ -348,7 +348,7 @@ test_expect_failure '--rebase overrides pull.rebase=preserve and flattens keep-m
>         test file3 = "$(git show HEAD:file3.t)"
>  '
>
> -test_expect_failure '--rebase with rebased upstream' '
> +test_expect_success '--rebase with rebased upstream' '
>
>         git remote add -f me . &&
>         git checkout copy &&
> @@ -366,7 +366,7 @@ test_expect_failure '--rebase with rebased upstream' '
>
>  '
>
> -test_expect_failure '--rebase with rebased default upstream' '
> +test_expect_success '--rebase with rebased default upstream' '
>
>         git update-ref refs/remotes/me/copy copy-orig &&
>         git checkout --track -b to-rebase2 me/copy &&
> @@ -377,7 +377,7 @@ test_expect_failure '--rebase with rebased default upstream' '
>
>  '
>
> -test_expect_failure 'rebased upstream + fetch + pull --rebase' '
> +test_expect_success 'rebased upstream + fetch + pull --rebase' '
>
>         git update-ref refs/remotes/me/copy copy-orig &&
>         git reset --hard to-rebase-orig &&
> @@ -409,7 +409,7 @@ test_expect_failure 'pull --rebase dies early with dirty working directory' '
>
>  '
>
> -test_expect_failure 'pull --rebase works on branch yet to be born' '
> +test_expect_success 'pull --rebase works on branch yet to be born' '
>         git rev-parse master >expect &&
>         mkdir empty_repo &&
>         (cd empty_repo &&
> @@ -456,14 +456,14 @@ test_expect_success 'setup for detecting upstreamed changes' '
>         )
>  '
>
> -test_expect_failure 'git pull --rebase detects upstreamed changes' '
> +test_expect_success 'git pull --rebase detects upstreamed changes' '
>         (cd dst &&
>          git pull --rebase &&
>          test -z "$(git ls-files -u)"
>         )
>  '
>
> -test_expect_failure 'setup for avoiding reapplying old patches' '
> +test_expect_success 'setup for avoiding reapplying old patches' '
>         (cd dst &&
>          test_might_fail git rebase --abort &&
>          git reset --hard origin/master
> @@ -485,7 +485,7 @@ test_expect_failure 'setup for avoiding reapplying old patches' '
>         )
>  '
>
> -test_expect_failure 'git pull --rebase does not reapply old patches' '
> +test_expect_success 'git pull --rebase does not reapply old patches' '
>         (cd dst &&
>          test_must_fail git pull --rebase &&
>          test 1 = $(find .git/rebase-apply -name "000*" | wc -l)
> diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh
> index 4176e11..56e7377 100755
> --- a/t/t5521-pull-options.sh
> +++ b/t/t5521-pull-options.sh
> @@ -19,7 +19,7 @@ test_expect_success 'git pull -q' '
>         test_must_be_empty out)
>  '
>
> -test_expect_failure 'git pull -q --rebase' '
> +test_expect_success 'git pull -q --rebase' '
>         mkdir clonedqrb &&
>         (cd clonedqrb && git init &&
>         git pull -q --rebase "../parent" >out 2>err &&
> @@ -38,7 +38,7 @@ test_expect_success 'git pull' '
>         test_must_be_empty out)
>  '
>
> -test_expect_failure 'git pull --rebase' '
> +test_expect_success 'git pull --rebase' '
>         mkdir clonedrb &&
>         (cd clonedrb && git init &&
>         git pull --rebase "../parent" >out 2>err &&
> @@ -54,7 +54,7 @@ test_expect_success 'git pull -v' '
>         test_must_be_empty out)
>  '
>
> -test_expect_failure 'git pull -v --rebase' '
> +test_expect_success 'git pull -v --rebase' '
>         mkdir clonedvrb &&
>         (cd clonedvrb && git init &&
>         git pull -v --rebase "../parent" >out 2>err &&
> diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
> index 1ffd837..dda3929 100755
> --- a/t/t7406-submodule-update.sh
> +++ b/t/t7406-submodule-update.sh
> @@ -11,8 +11,6 @@ submodule and "git submodule update --rebase/--merge" does not detach the HEAD.
>
>  . ./test-lib.sh
>
> -skip_all='skipping submodule update tests, requires git pull --rebase'
> -test_done
>
>  compare_head()
>  {
> --
> 2.1.4
>

^ permalink raw reply	[relevance 2%]

* Re: Diffing submodule does not yield complete logs for merge commits
  @ 2015-05-19 20:34  4%                     ` Stefan Beller
  2015-05-22  9:17  4%                       ` Roberto Tyley
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-05-19 20:34 UTC (permalink / raw)
  To: Robert Dailey; +Cc: Heiko Voigt, Johannes Schindelin, Jens Lehmann, Git

On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
<rcdailey.lists@gmail.com> wrote:
> How do you send your patches inline?

There are various ways to do so.
If you look at https://github.com/git/git/blob/master/Documentation/SubmittingPatches
and search for Thunderbird (I used to use Thunderbird for a long time
before switching to
git send-email, so I'll take that as an example) at the bottom:

    Thunderbird, KMail, GMail
    -------------------------

    See the MUA-SPECIFIC HINTS section of git-format-patch(1).

Ok, indirection is the fun part of computers. ;)
So you'd look at the man page of git format patch,
such as here http://git-scm.com/docs/git-format-patch
and scroll the way down to MUA-SPECIFIC HINTS, which offers
3 different ways of doing it. (decisions!)

> Do you use git send-email?

I do, but I remember my initial struggle with it (I will contribute only
one patch anyway, so why care?)

> I have
> tried that and it is horrible to setup. Do you just copy/paste the
> patch inline in your compose window?

Once setup correctly git formatpatch / send-email are actually very
convenient (e.g. git send-email HEAD^ --to=git@vger.kernel.org will
just work. And I have strong confidence in it continuing to work,
even when Git decides to revamp the preferred patch format,
line wrapping or other exotic stuff)

>
> It would be much simpler to fork Git, create a branch, make my change,
> and initiate a pull request. I can get email notifications on comments
> to my PR diff and address them with subsequent pushes to my branch
> (which would also automatically update the code review). Turn around
> times for collaborating on a change are much quicker via Github pull
> requests.

Github has indeed an excellent product, even free for open source.

This workflow discussion was a topic at the GitMerge2015 conference,
and there are essentially 2 groups, those who know how to send email
and those who complain about it. A solution was agreed on by nearly all
of the contributors. It would be awesome to have a git-to-email proxy,
such that you could do a git push <proxy> master:refs/for/mailinglist
and this proxy would convert the push into sending patch series to the
mailing list. It could even convert the following discussion back into
comments (on Github?) but as a first step we'd want to try out a one
way proxy.

Unfortunately nobody stepped up to actually do the work, yet :(

>
> I am willing to review the typical workflow for contributing via git
> on mailing lists but I haven't seen any informative reading material
> on this. I just find using command line to email patches and dealing
> with other issues not worth the trouble. Lack of syntax highlighting,
> lack of monospace font, the fact that I'm basically forced to install
> mail client software just to contribute a single git patch.
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 4%]

* Re: [PATCH v2] pull: handle --log=<n>
  @ 2015-05-19 21:43  3%             ` Dennis Kaarsemaker
  0 siblings, 0 replies; 200+ results
From: Dennis Kaarsemaker @ 2015-05-19 21:43 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Junio C Hamano, Johannes Schindelin, Paul Tan, Git Mailing List,
	Matthieu Moy, Ramkumar Ramachandra

On di, 2015-05-19 at 14:33 -0700, Stefan Beller wrote:
> On Tue, May 19, 2015 at 2:24 PM, Dennis Kaarsemaker
> <dennis@kaarsemaker.net> wrote:
> > On di, 2015-05-19 at 06:57 -0700, Junio C Hamano wrote:
> >> On Tue, May 19, 2015 at 6:35 AM, Johannes Schindelin
> >> <johannes.schindelin@gmx.de> wrote:
> >> >
> >> > On 2015-05-18 20:18, Junio C Hamano wrote:
> >> >>
> >> >> So I dunno.  I really wish test_commit didn't create tags and either
> >> >> left the tagging to the calling script.
> >> >
> >> > Or maybe just add a --tag flag to `test_commit` and use that in all cases where the tags were actually needed. Yeah, I think I like that option best.
> >>
> >> Thanks for inferring what I wanted to say but left unsaid due to my
> >> stupidity and
> >> lack of proofreading. I meant to follow "either left to the caller"
> >> with "or with an
> >> option" ;-)
> >
> > I took a stab at this, adding a --tag option to test_commit and adding
> > the option to the test_commit calls that need it (or removing tests'
> > reliance on these tags where appropriate, or removing tests' workarounds
> > for dealing with these tags when they don't want them), and the result
> > is 59 files changed, 280 insertions(+), 281 deletions(-)
> 
> I guess most of the line changes are just adding the --tag?
> And I'd guess (281-280) that there is no huge code inside of test_commit
> either, so I'd assume it doesn't add clutter, but rather cleans up....

Full stat:

 t/t0100-previous.sh                        |  6 +++---
 t/t1011-read-tree-sparse-checkout.sh       |  2 +-
 t/t1403-show-ref.sh                        |  6 +++---
 t/t1430-bad-ref-name.sh                    |  2 +-
 t/t1450-fsck.sh                            |  4 ++--
 t/t2018-checkout-branch.sh                 |  4 ++--
 t/t2020-checkout-detach.sh                 |  8 ++++----
 t/t2030-unresolve-info.sh                  | 10 +++++-----
 t/t3200-branch.sh                          |  2 +-
 t/t3211-peel-ref.sh                        |  2 +-
 t/t3307-notes-man.sh                       |  4 ++--
 t/t3308-notes-merge.sh                     | 10 +++++-----
 t/t3309-notes-merge-auto-resolve.sh        | 30
+++++++++++++++---------------
 t/t3310-notes-merge-manual-resolve.sh      | 10 +++++-----
 t/t3311-notes-merge-fanout.sh              |  2 +-
 t/t3400-rebase.sh                          |  6 +++---
 t/t3404-rebase-interactive.sh              | 22 +++++++++++-----------
 t/t3406-rebase-message.sh                  |  6 +++---
 t/t3410-rebase-preserve-dropped-merges.sh  | 14 +++++++-------
 t/t3411-rebase-preserve-around-merges.sh   | 14 +++++++-------
 t/t3414-rebase-preserve-onto.sh            | 14 +++++++-------
 t/t3416-rebase-onto-threedots.sh           | 12 ++++++------
 t/t3418-rebase-continue.sh                 |  4 ++--
 t/t3421-rebase-topology-linear.sh          | 22 +++++++++++-----------
 t/t3425-rebase-topology-merges.sh          | 20 ++++++++++----------
 t/t3507-cherry-pick-conflict.sh            |  8 ++++----
 t/t3508-cherry-pick-many-commits.sh        |  6 +++---
 t/t3510-cherry-pick-sequence.sh            | 16 ++++++++--------
 t/t3511-cherry-pick-x.sh                   |  2 +-
 t/t4131-apply-fake-ancestor.sh             |  8 ++++----
 t/t4152-am-subjects.sh                     |  2 +-
 t/t4202-log.sh                             | 14 +++++++-------
 t/t4207-log-decoration-colors.sh           |  8 +++-----
 t/t4300-merge-tree.sh                      | 62 +++++++++++++++++++++++++++++---------------------------------
 t/t5407-post-rewrite-hook.sh               | 12 ++++++------
 t/t5509-fetch-push-namespaces.sh           |  4 ++--
 t/t5510-fetch.sh                           |  4 ++--
 t/t5514-fetch-multiple.sh                  |  2 +-
 t/t5571-pre-push-hook.sh                   |  2 +-
 t/t5704-bundle.sh                          |  5 +----
 t/t6009-rev-list-parent.sh                 | 18 +++++++++---------
 t/t6010-merge-base.sh                      | 24 ++++++++++++------------
 t/t6016-rev-list-graph-simplify-history.sh | 22 +++++++++++-----------
 t/t6019-rev-list-ancestry-path.sh          | 18 +++++++++---------
 t/t6101-rev-parse-parents.sh               |  8 ++++----
 t/t6111-rev-list-treesame.sh               |  2 +-
 t/t6300-for-each-ref.sh                    |  1 -
 t/t7003-filter-branch.sh                   | 16 ++++++++--------
 t/t7007-show.sh                            |  8 ++++----
 t/t7012-skip-worktree-writing.sh           |  2 +-
 t/t7060-wtstatus.sh                        |  6 +++---
 t/t7111-reset-table.sh                     |  6 +++---
 t/t7407-submodule-foreach.sh               |  2 +-
 t/t7512-status-help.sh                     |  6 +++---
 t/t7606-merge-custom.sh                    |  8 ++++----
 t/t7607-merge-overwrite.sh                 |  6 +++---
 t/t7608-merge-messages.sh                  |  4 ++--
 t/t9502-gitweb-standalone-parse-output.sh  |  2 +-
 t/test-lib-functions.sh                    |  9 ++++++++-
 59 files changed, 278 insertions(+), 281 deletions(-)

> > A test run on master with GIT_TEST_LONG set causes 1138 calls to
> > test_commit on my system, of which 255 now use the --tag option
> > (measured with a really crude hack that INCR's some keys in redis at
> > appropriate points in test_commit).
> 
> ... 255 out of 1138 is awesome IMHO! Do you see an improvement in time as
> well (as in "time make test" is X% faster overall) ?

I have not measured, but will.

> > Is this interesting enough to turn into a proper patch series?
> 
> I'd think this is worth making a real patch, definitely!

OK.
-- 
Dennis Kaarsemaker
www.kaarsemaker.net

^ permalink raw reply	[relevance 3%]

* Re: [PUB]corrupt repos does not return error with `git fsck`
  @ 2015-05-20 18:19  4%       ` John Keeping
  0 siblings, 0 replies; 200+ results
From: John Keeping @ 2015-05-20 18:19 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Johannes Schindelin, Matthieu Moy, Faheem Mitha,
	git@vger.kernel.org

On Wed, May 20, 2015 at 11:02:14AM -0700, Stefan Beller wrote:
> $ git clone https://github.com/fmitha/SICL
> cd SICL
> $ git show 280c12ab49223c64c6f914944287a7d049cf4dd0
> fatal: bad object 280c12ab49223c64c6f914944287a7d049cf4dd0
> $ git show 12323213123 # just to be sure to have a different error
> message for non existing objects.
> fatal: ambiguous argument '12323213123': unknown revision or path not
> in the working tree.

I think 40 hex characters is special cased.  Using CGit as a repository
with a submodule so I can easily get an unrelated SHA1 and short name:

cgit $ git show $(git -C git rev-parse @)
fatal: bad object bb8577532add843833ebf8b5324f94f84cb71ca0
cgit $ git show $(git -C git rev-parse --short @)
fatal: ambiguous argument 'bb85775': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

^ permalink raw reply	[relevance 4%]

* [PATCH] submodule documentation: Reorder introductory paragraphs
@ 2015-05-20 23:11 21% Stefan Beller
  2015-05-21 13:04  4% ` Heiko Voigt
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Stefan Beller @ 2015-05-20 23:11 UTC (permalink / raw)
  To: gitster; +Cc: jrnieder, git, Stefan Beller, pasky, hvoigt

It's better to start the man page with a description of what submodules
actually are instead of saying what they are not.

Reorder the paragraphs such that
the first short paragraph introduces the submodule concept,
the second paragraph highlights the usage of the submodule command,
the third paragraph giving background information,
and finally the fourth paragraph discusing alternatives such
as subtrees and remotes, which we don't want to be confused with.

This ordering deepens the knowledge on submodules with each paragraph.
First the basic questions like "How/what" will be answered, while the
underlying concepts will be taught at a later time.

Making sure it is not confused with subtrees and remotes is not really
enhancing knowledge of submodules itself, but rather painting the big
picture of git concepts, so you could also argue to have it as the second
paragraph. Personally I think this may confuse readers, specially newcomers
though.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Documentation/git-submodule.txt | 54 ++++++++++++++++++++---------------------
 1 file changed, 26 insertions(+), 28 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 2c25916..6c38c0d 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -25,35 +25,12 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Submodules allow foreign repositories to be embedded within
-a dedicated subdirectory of the source tree, always pointed
-at a particular commit.
+Submodules allow other repositories to be embedded within
+a dedicated subdirectory of the source tree pointing
+at a particular commit in the other repository.
 
-They are not to be confused with remotes, which are meant mainly
-for branches of the same project; submodules are meant for
-different projects you would like to make part of your source tree,
-while the history of the two projects still stays completely
-independent and you cannot modify the contents of the submodule
-from within the main project.
-If you want to merge the project histories and want to treat the
-aggregated whole as a single project from then on, you may want to
-add a remote for the other project and use the 'subtree' merge strategy,
-instead of treating the other project as a submodule. Directories
-that come from both projects can be cloned and checked out as a whole
-if you choose to go that route.
-
-Submodules are composed from a so-called `gitlink` tree entry
-in the main repository that refers to a particular commit object
-within the inner repository that is completely separate.
-A record in the `.gitmodules` (see linkgit:gitmodules[5]) file at the
-root of the source tree assigns a logical name to the submodule and
-describes the default URL the submodule shall be cloned from.
-The logical name can be used for overriding this URL within your
-local repository configuration (see 'submodule init').
-
-This command will manage the tree entries and contents of the
-gitmodules file for you, as well as inspect the status of your
-submodules and update them.
+This command will manage the submodules for you, as well as
+inspect the status of your submodules and update them.
 When adding a new submodule to the tree, the 'add' subcommand
 is to be used.  However, when pulling a tree containing submodules,
 these will not be checked out by default;
@@ -64,6 +41,27 @@ using the 'status' subcommand and get a detailed overview of the
 difference between the index and checkouts using the 'summary'
 subcommand.
 
+Submodules are composed from a so-called `gitlink` tree entry
+in the main repository that refers to a particular commit object
+within the inner repository that is completely separate.
+A record in the `.gitmodules` (see linkgit:gitmodules[5]) file at the
+root of the source tree assigns a logical name to the submodule and
+describes the default URL the submodule shall be cloned from.
+The logical name can be used for overriding this URL within your
+local repository configuration (see 'submodule init').
+
+Submodules are not to be confused with remotes, which are meant
+mainly for branches of the same project; submodules are meant for
+different projects you would like to make part of your source tree,
+while the history of the two projects still stays completely
+independent and you cannot modify the contents of the submodule
+from within the main project.
+If you want to merge the project histories and want to treat the
+aggregated whole as a single project from then on, you may want to
+add a remote for the other project and use the 'subtree' merge strategy,
+instead of treating the other project as a submodule. Directories
+that come from both projects can be cloned and checked out as a whole
+if you choose to go that route.
 
 COMMANDS
 --------
-- 
2.4.0.194.gc518059

^ permalink raw reply related	[relevance 21%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-20 23:11 21% [PATCH] submodule documentation: Reorder introductory paragraphs Stefan Beller
@ 2015-05-21 13:04  4% ` Heiko Voigt
  2015-05-21 17:24  6% ` Junio C Hamano
  2015-05-21 20:03  4% ` Philip Oakley
  2 siblings, 0 replies; 200+ results
From: Heiko Voigt @ 2015-05-21 13:04 UTC (permalink / raw)
  To: Stefan Beller; +Cc: gitster, jrnieder, git, pasky

On Wed, May 20, 2015 at 04:11:57PM -0700, Stefan Beller wrote:
> It's better to start the man page with a description of what submodules
> actually are instead of saying what they are not.
> 
> Reorder the paragraphs such that
> the first short paragraph introduces the submodule concept,
> the second paragraph highlights the usage of the submodule command,
> the third paragraph giving background information,
> and finally the fourth paragraph discusing alternatives such
> as subtrees and remotes, which we don't want to be confused with.
> 
> This ordering deepens the knowledge on submodules with each paragraph.
> First the basic questions like "How/what" will be answered, while the
> underlying concepts will be taught at a later time.
> 
> Making sure it is not confused with subtrees and remotes is not really
> enhancing knowledge of submodules itself, but rather painting the big
> picture of git concepts, so you could also argue to have it as the second
> paragraph. Personally I think this may confuse readers, specially newcomers
> though.
> 
> Signed-off-by: Stefan Beller <sbeller@google.com>

Looks good to me.

Cheers Heiko

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-20 23:11 21% [PATCH] submodule documentation: Reorder introductory paragraphs Stefan Beller
  2015-05-21 13:04  4% ` Heiko Voigt
@ 2015-05-21 17:24  6% ` Junio C Hamano
  2015-05-21 17:43  7%   ` Stefan Beller
  2015-05-21 20:03  4% ` Philip Oakley
  2 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-05-21 17:24 UTC (permalink / raw)
  To: Stefan Beller; +Cc: jrnieder, git, pasky, hvoigt

Stefan Beller <sbeller@google.com> writes:

> Reorder the paragraphs such that
> the first short paragraph introduces the submodule concept,
> the second paragraph highlights the usage of the submodule command,
> the third paragraph giving background information,
> and finally the fourth paragraph discusing alternatives such
> as subtrees and remotes, which we don't want to be confused with.
>
> This ordering deepens the knowledge on submodules with each paragraph.
> First the basic questions like "How/what" will be answered, while the
> underlying concepts will be taught at a later time.

Sounds good.

> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
> index 2c25916..6c38c0d 100644
> --- a/Documentation/git-submodule.txt
> +++ b/Documentation/git-submodule.txt
> @@ -25,35 +25,12 @@ SYNOPSIS
>  
>  DESCRIPTION
>  -----------
> -Submodules allow foreign repositories to be embedded within
> -a dedicated subdirectory of the source tree, always pointed
> -at a particular commit.
> +Submodules allow other repositories to be embedded within
> +a dedicated subdirectory of the source tree pointing
> +at a particular commit in the other repository.

Not a new problem, but I can misread this as if it requires the
top-level superproject to have one single dedicated directory D to
house all the foreign projects under it, D/project1, D/project2, ...

> -This command will manage the tree entries and contents of the
> -gitmodules file for you, as well as inspect the status of your
> -submodules and update them.
> +This command will manage the submodules for you, as well as
> +inspect the status of your submodules and update them.

Not a new problem, but does the command really "manage them for
you"?  I view it more like "You can use this command to manage,
inspect and update the submodules".

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-21 17:24  6% ` Junio C Hamano
@ 2015-05-21 17:43  7%   ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-21 17:43 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jonathan Nieder, git@vger.kernel.org, Heiko Voigt

On Thu, May 21, 2015 at 10:24 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> Reorder the paragraphs such that
>> the first short paragraph introduces the submodule concept,
>> the second paragraph highlights the usage of the submodule command,
>> the third paragraph giving background information,
>> and finally the fourth paragraph discusing alternatives such
>> as subtrees and remotes, which we don't want to be confused with.
>>
>> This ordering deepens the knowledge on submodules with each paragraph.
>> First the basic questions like "How/what" will be answered, while the
>> underlying concepts will be taught at a later time.
>
> Sounds good.
>
>> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
>> index 2c25916..6c38c0d 100644
>> --- a/Documentation/git-submodule.txt
>> +++ b/Documentation/git-submodule.txt
>> @@ -25,35 +25,12 @@ SYNOPSIS
>>
>>  DESCRIPTION
>>  -----------
>> -Submodules allow foreign repositories to be embedded within
>> -a dedicated subdirectory of the source tree, always pointed
>> -at a particular commit.
>> +Submodules allow other repositories to be embedded within
>> +a dedicated subdirectory of the source tree pointing
>> +at a particular commit in the other repository.
>
> Not a new problem, but I can misread this as if it requires the
> top-level superproject to have one single dedicated directory D to
> house all the foreign projects under it, D/project1, D/project2, ...

I agree, maybe we should reword the paragraphs themselves as well.

    Submodules allow you to keep another Git repository in a subdirectory
    of your repository. The other repository has its own history, which does not
    interfere with the history of the current repository. This can be used to
    have external dependencies such as libraries for example.

>
>> -This command will manage the tree entries and contents of the
>> -gitmodules file for you, as well as inspect the status of your
>> -submodules and update them.
>> +This command will manage the submodules for you, as well as
>> +inspect the status of your submodules and update them.
>
> Not a new problem, but does the command really "manage them for
> you"?  I view it more like "You can use this command to manage,
> inspect and update the submodules".

I agree.

^ permalink raw reply	[relevance 7%]

* [PATCH] submodule documentation: Rewrite introductory paragraphs
@ 2015-05-21 19:01 23% Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-21 19:01 UTC (permalink / raw)
  To: gitster; +Cc: jrnieder, git, hvoigt, Stefan Beller

It's better to start the man page with a description of what submodules
actually are instead of saying what they are not.

Reorder the paragraphs such that
the first short paragraph introduces the submodule concept,
the second paragraph highlights the usage of the submodule command,
the third paragraph giving background information,
and finally the fourth paragraph discusing alternatives such
as subtrees and remotes, which we don't want to be confused with.

This ordering deepens the knowledge on submodules with each paragraph.
First the basic questions like "How/what" will be answered, while the
underlying concepts will be taught at a later time.

Making sure it is not confused with subtrees and remotes is not really
enhancing knowledge of submodules itself, but rather painting the big
picture of git concepts, so you could also argue to have it as the second
paragraph. Personally I think this may confuse readers, specially newcomers
though.

Signed-off-by: Stefan Beller <sbeller@google.com>
---

I rewrote the first 2 paragraphs as well now. I think it doesn't make sense
to mention any subcommand in the description section, so I removed 
 "When adding a new submodule to the tree, the 'add' subcommand is to be used."
though I kept the warning about submodules not being autmatically updated by
clone and pull. All other subcommands are gone from the description.


>> Not a new problem, but does the command really "manage them for
>> you"?  I view it more like "You can use this command to manage,
>> inspect and update the submodules".
>
> I agree.

Trying to find a better wording I looked more closely at other man pages to get
consistent with them. Most of them (e.g. add, status, rebase, revert) just describe
what they do in a short manner.

Now I am looking at the subtree man page and it looks as if it written in a similar style
to the submodules man page, the first 2 paragraphs give a short description what
subtrees do (not the command, but the concept) including an example.
The third paragraph then starts with "Subtrees are not to be confused
with submodules, ..." which I'd not want to see as early in a man page.
So in the subtree man page there is no such paragraph as
 
    This command can do this and that.

but rather the concept and examples are given.

 Documentation/git-submodule.txt | 50 ++++++++++++++++++-----------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 2c25916..97718cf 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -25,22 +25,17 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Submodules allow foreign repositories to be embedded within
-a dedicated subdirectory of the source tree, always pointed
-at a particular commit.
+This command will inspect, update and manage submodules.
 
-They are not to be confused with remotes, which are meant mainly
-for branches of the same project; submodules are meant for
-different projects you would like to make part of your source tree,
-while the history of the two projects still stays completely
-independent and you cannot modify the contents of the submodule
-from within the main project.
-If you want to merge the project histories and want to treat the
-aggregated whole as a single project from then on, you may want to
-add a remote for the other project and use the 'subtree' merge strategy,
-instead of treating the other project as a submodule. Directories
-that come from both projects can be cloned and checked out as a whole
-if you choose to go that route.
+Submodules allow you to keep another Git repository in a subdirectory
+of your repository. The other repository has its own history, which does not
+interfere with the history of the current repository. This can be used to
+have external dependencies such as libraries for example.
+
+When cloning or pulling a repository containing submodules however,
+these will not be checked out by default; the 'init' and 'update'
+subcommands will maintain submodules checked out and at
+appropriate revision in your working tree.
 
 Submodules are composed from a so-called `gitlink` tree entry
 in the main repository that refers to a particular commit object
@@ -51,19 +46,18 @@ describes the default URL the submodule shall be cloned from.
 The logical name can be used for overriding this URL within your
 local repository configuration (see 'submodule init').
 
-This command will manage the tree entries and contents of the
-gitmodules file for you, as well as inspect the status of your
-submodules and update them.
-When adding a new submodule to the tree, the 'add' subcommand
-is to be used.  However, when pulling a tree containing submodules,
-these will not be checked out by default;
-the 'init' and 'update' subcommands will maintain submodules
-checked out and at appropriate revision in your working tree.
-You can briefly inspect the up-to-date status of your submodules
-using the 'status' subcommand and get a detailed overview of the
-difference between the index and checkouts using the 'summary'
-subcommand.
-
+Submodules are not to be confused with remotes, which are meant
+mainly for branches of the same project; submodules are meant for
+different projects you would like to make part of your source tree,
+while the history of the two projects still stays completely
+independent and you cannot modify the contents of the submodule
+from within the main project.
+If you want to merge the project histories and want to treat the
+aggregated whole as a single project from then on, you may want to
+add a remote for the other project and use the 'subtree' merge strategy,
+instead of treating the other project as a submodule. Directories
+that come from both projects can be cloned and checked out as a whole
+if you choose to go that route.
 
 COMMANDS
 --------
-- 
2.4.0.194.gc518059

^ permalink raw reply related	[relevance 23%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-20 23:11 21% [PATCH] submodule documentation: Reorder introductory paragraphs Stefan Beller
  2015-05-21 13:04  4% ` Heiko Voigt
  2015-05-21 17:24  6% ` Junio C Hamano
@ 2015-05-21 20:03  4% ` Philip Oakley
  2015-05-21 22:08  7%   ` Stefan Beller
  2 siblings, 1 reply; 200+ results
From: Philip Oakley @ 2015-05-21 20:03 UTC (permalink / raw)
  To: Stefan Beller, gitster; +Cc: jrnieder, git, Stefan Beller, pasky, hvoigt

From: "Stefan Beller" <sbeller@google.com>
> It's better to start the man page with a description of what 
> submodules
> actually are instead of saying what they are not.
>
> Reorder the paragraphs such that
> the first short paragraph introduces the submodule concept,
> the second paragraph highlights the usage of the submodule command,
> the third paragraph giving background information,
> and finally the fourth paragraph discusing alternatives such
> as subtrees and remotes, which we don't want to be confused with.
>
> This ordering deepens the knowledge on submodules with each paragraph.
> First the basic questions like "How/what" will be answered, while the
> underlying concepts will be taught at a later time.
>
> Making sure it is not confused with subtrees and remotes is not really
> enhancing knowledge of submodules itself, but rather painting the big
> picture of git concepts, so you could also argue to have it as the 
> second
> paragraph. Personally I think this may confuse readers, specially 
> newcomers
> though.
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
> Documentation/git-submodule.txt | 54 
> ++++++++++++++++++++---------------------
> 1 file changed, 26 insertions(+), 28 deletions(-)
>
> diff --git a/Documentation/git-submodule.txt 
> b/Documentation/git-submodule.txt
> index 2c25916..6c38c0d 100644
> --- a/Documentation/git-submodule.txt
> +++ b/Documentation/git-submodule.txt
> @@ -25,35 +25,12 @@ SYNOPSIS
>
> DESCRIPTION
> -----------
> -Submodules allow foreign repositories to be embedded within
> -a dedicated subdirectory of the source tree, always pointed
> -at a particular commit.
> +Submodules allow other repositories to be embedded within
> +a dedicated subdirectory of the source tree pointing
> +at a particular commit in the other repository.
>
> -They are not to be confused with remotes, which are meant mainly
> -for branches of the same project; submodules are meant for
> -different projects you would like to make part of your source tree,
> -while the history of the two projects still stays completely
> -independent and you cannot modify the contents of the submodule
> -from within the main project.
> -If you want to merge the project histories and want to treat the
> -aggregated whole as a single project from then on, you may want to
> -add a remote for the other project and use the 'subtree' merge 
> strategy,
> -instead of treating the other project as a submodule. Directories
> -that come from both projects can be cloned and checked out as a whole
> -if you choose to go that route.
> -
> -Submodules are composed from a so-called `gitlink` tree entry
> -in the main repository that refers to a particular commit object
> -within the inner repository that is completely separate.
> -A record in the `.gitmodules` (see linkgit:gitmodules[5]) file at the
> -root of the source tree assigns a logical name to the submodule and
> -describes the default URL the submodule shall be cloned from.
> -The logical name can be used for overriding this URL within your
> -local repository configuration (see 'submodule init').
> -
> -This command will manage the tree entries and contents of the
> -gitmodules file for you, as well as inspect the status of your
> -submodules and update them.
> +This command will manage the submodules for you, as well as
> +inspect the status of your submodules and update them.
> When adding a new submodule to the tree, the 'add' subcommand
> is to be used.  However, when pulling a tree containing submodules,
> these will not be checked out by default;
> @@ -64,6 +41,27 @@ using the 'status' subcommand and get a detailed 
> overview of the
> difference between the index and checkouts using the 'summary'
> subcommand.
>
> +Submodules are composed from a so-called `gitlink` tree entry
> +in the main repository that refers to a particular commit object
> +within the inner repository that is completely separate.
> +A record in the `.gitmodules` (see linkgit:gitmodules[5]) file at the
> +root of the source tree assigns a logical name to the submodule and
> +describes the default URL the submodule shall be cloned from.
> +The logical name can be used for overriding this URL within your
> +local repository configuration (see 'submodule init').
> +
> +Submodules are not to be confused with remotes, which are meant
> +mainly for branches of the same project;

This use of 'branches' didn't work for me. "remotes are meant mainly for 
branches of the same project" ?

>  submodules are meant for
> +different projects you would like to make part of your source tree,
> +while the history of the two projects still stays completely
> +independent and you cannot modify the contents of the submodule
> +from within the main project.
> +If you want to merge the project histories and want to treat the
> +aggregated whole as a single project from then on, you may want to
> +add a remote for the other project and use the 'subtree' merge 
> strategy,
> +instead of treating the other project as a submodule. Directories
> +that come from both projects can be cloned and checked out as a whole
> +if you choose to go that route.
>
--
Philip 

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-21 20:03  4% ` Philip Oakley
@ 2015-05-21 22:08  7%   ` Stefan Beller
  2015-05-22  6:59  4%     ` Philip Oakley
  2015-05-22 14:36  4%     ` Junio C Hamano
  0 siblings, 2 replies; 200+ results
From: Stefan Beller @ 2015-05-21 22:08 UTC (permalink / raw)
  To: Philip Oakley
  Cc: Junio C Hamano, Jonathan Nieder, git@vger.kernel.org, Petr Baudis,
	Heiko Voigt

On Thu, May 21, 2015 at 1:03 PM, Philip Oakley <philipoakley@iee.org> wrote:
>> +Submodules are not to be confused with remotes, which are meant
>> +mainly for branches of the same project;
>
>
> This use of 'branches' didn't work for me. "remotes are meant mainly for
> branches of the same project" ?
>

Maybe

    Submodules should not be confused with remote repositories, which are
    meant to track the same repository, just at another location; ...

? Though I'm not yet completely happy with that either.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-21 22:08  7%   ` Stefan Beller
@ 2015-05-22  6:59  4%     ` Philip Oakley
  2015-05-22 14:36  4%     ` Junio C Hamano
  1 sibling, 0 replies; 200+ results
From: Philip Oakley @ 2015-05-22  6:59 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Junio C Hamano, Jonathan Nieder, git, Petr Baudis, Heiko Voigt

From: "Stefan Beller" <sbeller@google.com>
> On Thu, May 21, 2015 at 1:03 PM, Philip Oakley <philipoakley@iee.org> 
> wrote:
>>> +Submodules are not to be confused with remotes, which are meant
>>> +mainly for branches of the same project;
>>
>>
>> This use of 'branches' didn't work for me. "remotes are meant mainly 
>> for
>> branches of the same project" ?
>>
>
> Maybe
>
>    Submodules should not be confused with remote repositories, which 
> are
>    meant to track the same repository, just at another location; ...
>
> ? Though I'm not yet completely happy with that either.
>

I like that better. I was going to check what the git glossary said a 
remote was, but the commute to work beckons...

Philip 

^ permalink raw reply	[relevance 4%]

* [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
@ 2015-05-22  8:33  3% Roberto Tyley
  2015-05-22  9:42  2% ` Johannes Schindelin
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Roberto Tyley @ 2015-05-22  8:33 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Robert Dailey, Heiko Voigt, Johannes Schindelin, Jens Lehmann,
	Git, Thomas Ferris Nicolaisen, emma

On Tuesday, 19 May 2015, Stefan Beller <sbeller@google.com> wrote:
> On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
> <rcdailey.lists@gmail.com> wrote:
> > How do you send your patches inline?
[snip]
> This workflow discussion was a topic at the GitMerge2015 conference,
> and there are essentially 2 groups, those who know how to send email
> and those who complain about it. A solution was agreed on by nearly all
> of the contributors. It would be awesome to have a git-to-email proxy,
> such that you could do a git push <proxy> master:refs/for/mailinglist
> and this proxy would convert the push into sending patch series to the
> mailing list. It could even convert the following discussion back into
> comments (on Github?) but as a first step we'd want to try out a one
> way proxy.
>
> Unfortunately nobody stepped up to actually do the work, yet :(


Hello, I'm stepping up to do that work :) Or at least, I'm implementing a
one-way GitHub PR -> Mailing list tool, called submitGit:

https://submitgit.herokuapp.com/

Here's what a user does:

* create a PR on https://github.com/git/git
* logs into https://submitgit.herokuapp.com/ with GitHub auth
* selects their PR on https://submitgit.herokuapp.com/git/git/pulls
* gets submitGit to email the PR as patches to themselves, in order to
check it looks ok
* when they're ready, get submitGit to send it to the mailing list on
their behalf

All discussion of the patch *stays* on the mailing list - I'm not
attempting to change
anything about the Git community process, other than make it easier
for a wider group
people to submit patches to the list.

For hard-core contributors to Git, I'd imagine that git format-patch &
send-email
remain the fastest way to do their work. But those tools are _unfamiliar to the
majority of Git users_ - so submitGit aims to cater to those users, because they
definitely have valuable contributions to make, which would be tragic
to throw away.

I've been working on submitGit in my spare time for the past few
weeks, and there
are still features I plan to add (like guiding the user to more
'correct' word wrapping,
sign-off, etc), but given this discussion, I wanted to chime in and
let people know
what's here so far. It would be great if people could take the time to
explore the tool
(you don't have to raise a git/git PR in order to try sending one *to
yourself*, for
instance) and give feedback on list, or in GitHub issues:

https://github.com/rtyley/submitgit/issues

I've been lucky enough to discuss the ideas around submitGit with a
few people at
the Git-Merge conf, so thanks to Peff, Thomas Ferris Nicolaisen, and Emma Jane
Hogbin Westby for listening to me (not to imply their endorsement of
what I've done,
just thanks for talking about it!).

Roberto

^ permalink raw reply	[relevance 3%]

* Re: Diffing submodule does not yield complete logs for merge commits
  2015-05-19 20:34  4%                     ` Stefan Beller
@ 2015-05-22  9:17  4%                       ` Roberto Tyley
  0 siblings, 0 replies; 200+ results
From: Roberto Tyley @ 2015-05-22  9:17 UTC (permalink / raw)
  Cc: Git

On Tuesday, 19 May 2015, Stefan Beller <sbeller@google.com> wrote:
> On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
> <rcdailey.lists@gmail.com> wrote:
> > How do you send your patches inline?
>
> This workflow discussion was a topic at the GitMerge2015 conference,
> and there are essentially 2 groups, those who know how to send email
> and those who complain about it. A solution was agreed on by nearly all
> of the contributors. It would be awesome to have a git-to-email proxy,
> such that you could do a git push <proxy> master:refs/for/mailinglist
> and this proxy would convert the push into sending patch series to the
> mailing list. It could even convert the following discussion back into
> comments (on Github?) but as a first step we'd want to try out a one
> way proxy.
>
> Unfortunately nobody stepped up to actually do the work, yet :(

I've replied to this on a separate announcement thread on the Git mailing
list here:

http://thread.gmane.org/gmane.comp.version-control.git/269699

...I've created a new tool called submitGit, which aims to help.

> > I am willing to review the typical workflow for contributing via git
> > on mailing lists but I haven't seen any informative reading material
> > on this. I just find using command line to email patches and dealing
> > with other issues not worth the trouble. Lack of syntax highlighting,
> > lack of monospace font, the fact that I'm basically forced to install
> > mail client software just to contribute a single git patch.

I'd be interested to know what you think!

Roberto

^ permalink raw reply	[relevance 4%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22  8:33  3% [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs") Roberto Tyley
@ 2015-05-22  9:42  2% ` Johannes Schindelin
  2015-05-22 14:41  2%   ` Johannes Schindelin
    2015-05-22 16:53  4% ` Stefan Beller
  2 siblings, 1 reply; 200+ results
From: Johannes Schindelin @ 2015-05-22  9:42 UTC (permalink / raw)
  To: Roberto Tyley
  Cc: Stefan Beller, Robert Dailey, Heiko Voigt, Jens Lehmann, Git,
	Thomas Ferris Nicolaisen, emma

Hi Roberto,

On 2015-05-22 10:33, Roberto Tyley wrote:
> On Tuesday, 19 May 2015, Stefan Beller <sbeller@google.com> wrote:
>> On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
>> <rcdailey.lists@gmail.com> wrote:
>> > How do you send your patches inline?
> [snip]
>> This workflow discussion was a topic at the GitMerge2015 conference,
>> and there are essentially 2 groups, those who know how to send email
>> and those who complain about it. A solution was agreed on by nearly all
>> of the contributors. It would be awesome to have a git-to-email proxy,
>> such that you could do a git push <proxy> master:refs/for/mailinglist
>> and this proxy would convert the push into sending patch series to the
>> mailing list. It could even convert the following discussion back into
>> comments (on Github?) but as a first step we'd want to try out a one
>> way proxy.
>>
>> Unfortunately nobody stepped up to actually do the work, yet :(
> 
> 
> Hello, I'm stepping up to do that work :) Or at least, I'm implementing a
> one-way GitHub PR -> Mailing list tool, called submitGit:
> 
> https://submitgit.herokuapp.com/

Wow!!!

I will make sure to test it with a couple of patches I want to submit anyway.

Thanks so much!
Dscho

^ permalink raw reply	[relevance 2%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-21 22:08  7%   ` Stefan Beller
  2015-05-22  6:59  4%     ` Philip Oakley
@ 2015-05-22 14:36  4%     ` Junio C Hamano
  2015-05-22 17:05  4%       ` Stefan Beller
  1 sibling, 1 reply; 200+ results
From: Junio C Hamano @ 2015-05-22 14:36 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Philip Oakley, Jonathan Nieder, git@vger.kernel.org, Petr Baudis,
	Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

> On Thu, May 21, 2015 at 1:03 PM, Philip Oakley <philipoakley@iee.org> wrote:
>>> +Submodules are not to be confused with remotes, which are meant
>>> +mainly for branches of the same project;
>>
>> This use of 'branches' didn't work for me. "remotes are meant mainly for
>> branches of the same project" ?

The "branch" in the original is used in a much wider sense than
usual branch (i.e. ref/heads/ thing you have locally); it refers to
forks of the same project but with a bit of twist.  When you say
repository A is a fork of the same project as my local repository,
you would give an impression that A is not the authoritative copy of
the project.  But you can say my repository and that repository A
are branches of the same project, you give zero information as to
A's authoritativeness.

>     Submodules should not be confused with remote repositories, which are
>     meant to track the same repository, just at another location; ...

I do not think this is a great improvement.  You now conflated
"repository" to mean "project" in the latter half of the sentence,
while you are trying to explain what a "remote repository" is.

Your copy of git.git is not the same repository as mine; they have
different histories.  Both repositories are used to work on the same
project.  "submoules are not remotes, which are other repositories
of the same project", perhaps?

^ permalink raw reply	[relevance 4%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22  9:42  2% ` Johannes Schindelin
@ 2015-05-22 14:41  2%   ` Johannes Schindelin
  2015-05-22 17:14  2%     ` Philip Oakley
  0 siblings, 1 reply; 200+ results
From: Johannes Schindelin @ 2015-05-22 14:41 UTC (permalink / raw)
  To: Roberto Tyley
  Cc: Stefan Beller, Robert Dailey, Heiko Voigt, Jens Lehmann, Git,
	Thomas Ferris Nicolaisen, emma

Hi Roberto,

On 2015-05-22 11:42, Johannes Schindelin wrote:

> On 2015-05-22 10:33, Roberto Tyley wrote:
>> On Tuesday, 19 May 2015, Stefan Beller <sbeller@google.com> wrote:
>>> On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
>>> <rcdailey.lists@gmail.com> wrote:
>>> > How do you send your patches inline?
>> [snip]
>>> This workflow discussion was a topic at the GitMerge2015 conference,
>>> and there are essentially 2 groups, those who know how to send email
>>> and those who complain about it. A solution was agreed on by nearly all
>>> of the contributors. It would be awesome to have a git-to-email proxy,
>>> such that you could do a git push <proxy> master:refs/for/mailinglist
>>> and this proxy would convert the push into sending patch series to the
>>> mailing list. It could even convert the following discussion back into
>>> comments (on Github?) but as a first step we'd want to try out a one
>>> way proxy.
>>>
>>> Unfortunately nobody stepped up to actually do the work, yet :(
>>
>>
>> Hello, I'm stepping up to do that work :) Or at least, I'm implementing a
>> one-way GitHub PR -> Mailing list tool, called submitGit:
>>
>> https://submitgit.herokuapp.com/
> 
> Wow!!!
> 
> I will make sure to test it with a couple of patches I want to submit anyway.

I just tried this with https://github.com/git/git/pull/139 and would like to tell you about two wishes I had immediately:

- If the author of a patch I am submitting is not myself, could submitGit maybe add that `From: ` line at the top of the mail?
- The patch series is sent without a cover letter, but it would be *really* great if a path series consisting of more than one patch could have the initial comment of the Pull Request as a cover letter, with the link to the original Pull Request at the bottom? This would also be the mail to use in the "In-reply-yo" header instead of the first patch.

Thanks so much!
Dscho

^ permalink raw reply	[relevance 2%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22  8:33  3% [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs") Roberto Tyley
  2015-05-22  9:42  2% ` Johannes Schindelin
  @ 2015-05-22 16:53  4% ` Stefan Beller
  2 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-22 16:53 UTC (permalink / raw)
  To: Roberto Tyley
  Cc: Robert Dailey, Heiko Voigt, Johannes Schindelin, Jens Lehmann,
	Git, Thomas Ferris Nicolaisen, emma

On Fri, May 22, 2015 at 1:33 AM, Roberto Tyley <roberto.tyley@gmail.com> wrote:
> On Tuesday, 19 May 2015, Stefan Beller <sbeller@google.com> wrote:
>> On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
>> <rcdailey.lists@gmail.com> wrote:
>> > How do you send your patches inline?
> [snip]
>> This workflow discussion was a topic at the GitMerge2015 conference,
>> and there are essentially 2 groups, those who know how to send email
>> and those who complain about it. A solution was agreed on by nearly all
>> of the contributors. It would be awesome to have a git-to-email proxy,
>> such that you could do a git push <proxy> master:refs/for/mailinglist
>> and this proxy would convert the push into sending patch series to the
>> mailing list. It could even convert the following discussion back into
>> comments (on Github?) but as a first step we'd want to try out a one
>> way proxy.
>>
>> Unfortunately nobody stepped up to actually do the work, yet :(
>
>
> Hello, I'm stepping up to do that work :) Or at least, I'm implementing a
> one-way GitHub PR -> Mailing list tool, called submitGit:

Cool!
I will try that with the next patch I want to submit.

>
> https://submitgit.herokuapp.com/
>
> Here's what a user does:
>
> * create a PR on https://github.com/git/git

When looking at https://github.com/git/git

    Git Source Code Mirror - This is a publish-only repository and all
    pull requests are ignored. Please follow Documentation/SubmittingPatches
    procedure for any of your improvements.

Once this tool has proven to be usable (in a few days?), we want to reword that.

    Guidelines for submitting patches to Git. Half this document covers how
    to send a patch via email without it getting corrupted - which submitGit
    will do for you - but the other half is very useful, giving guidance on what
    good patches for the Git project should look like.

If it turns out this tool is widely used we may want to consider splitting up
SubmittingPatches inside git.git into two files, one dealing with the contents
i.e. How to write good, reviewable commits, following the coding guide lines
and having a proper sign off, and another document on how to get your
contributions
upstream (email, pull request, ...)

> * logs into https://submitgit.herokuapp.com/ with GitHub auth
> * selects their PR on https://submitgit.herokuapp.com/git/git/pulls
> * gets submitGit to email the PR as patches to themselves, in order to
> check it looks ok
> * when they're ready, get submitGit to send it to the mailing list on
> their behalf
>
> All discussion of the patch *stays* on the mailing list - I'm not
> attempting to change
> anything about the Git community process, other than make it easier
> for a wider group
> people to submit patches to the list.
>
> For hard-core contributors to Git, I'd imagine that git format-patch &
> send-email
> remain the fastest way to do their work. But those tools are _unfamiliar to the
> majority of Git users_ - so submitGit aims to cater to those users, because they
> definitely have valuable contributions to make, which would be tragic
> to throw away.
>
> I've been working on submitGit in my spare time for the past few
> weeks, and there
> are still features I plan to add (like guiding the user to more
> 'correct' word wrapping,
> sign-off, etc), but given this discussion, I wanted to chime in and
> let people know
> what's here so far. It would be great if people could take the time to
> explore the tool
> (you don't have to raise a git/git PR in order to try sending one *to
> yourself*, for
> instance) and give feedback on list, or in GitHub issues:
>
> https://github.com/rtyley/submitgit/issues
>
> I've been lucky enough to discuss the ideas around submitGit with a
> few people at
> the Git-Merge conf, so thanks to Peff, Thomas Ferris Nicolaisen, and Emma Jane
> Hogbin Westby for listening to me (not to imply their endorsement of
> what I've done,
> just thanks for talking about it!).

Wow!
Thanks for doing this,
Stefan

>
> Roberto

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-22 14:36  4%     ` Junio C Hamano
@ 2015-05-22 17:05  4%       ` Stefan Beller
  2015-05-22 17:26  4%         ` Junio C Hamano
  2015-05-22 17:35  7%         ` Philip Oakley
  0 siblings, 2 replies; 200+ results
From: Stefan Beller @ 2015-05-22 17:05 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Philip Oakley, Jonathan Nieder, git@vger.kernel.org, Petr Baudis,
	Heiko Voigt

On Fri, May 22, 2015 at 7:36 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> On Thu, May 21, 2015 at 1:03 PM, Philip Oakley <philipoakley@iee.org> wrote:
>>>> +Submodules are not to be confused with remotes, which are meant
>>>> +mainly for branches of the same project;
>>>
>>> This use of 'branches' didn't work for me. "remotes are meant mainly for
>>> branches of the same project" ?
>
> The "branch" in the original is used in a much wider sense than
> usual branch (i.e. ref/heads/ thing you have locally); it refers to
> forks of the same project but with a bit of twist.  When you say
> repository A is a fork of the same project as my local repository,
> you would give an impression that A is not the authoritative copy of
> the project.  But you can say my repository and that repository A
> are branches of the same project, you give zero information as to
> A's authoritativeness.

While this is correct, I think it is also confusing, because 'branch'
is a command which deals with local branches only in my perception
To deal with remote branches you need to use the commands
{remote, fetch, pull}.

So when someone mentions "branch" I need to think of local operations
in one repository and not on different distributed histories.

>
>>     Submodules should not be confused with remote repositories, which are
>>     meant to track the same repository, just at another location; ...
>
> I do not think this is a great improvement.  You now conflated
> "repository" to mean "project" in the latter half of the sentence,
> while you are trying to explain what a "remote repository" is.

That's true.

>
> Your copy of git.git is not the same repository as mine; they have
> different histories.  Both repositories are used to work on the same
> project.  "submoules are not remotes, which are other repositories
> of the same project", perhaps?

That makes sense.

^ permalink raw reply	[relevance 4%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22 14:41  2%   ` Johannes Schindelin
@ 2015-05-22 17:14  2%     ` Philip Oakley
  2015-05-22 19:58  2%       ` Johannes Schindelin
  0 siblings, 1 reply; 200+ results
From: Philip Oakley @ 2015-05-22 17:14 UTC (permalink / raw)
  To: Roberto Tyley
  Cc: Stefan Beller, Robert Dailey, Heiko Voigt, Jens Lehmann, Git,
	Thomas Ferris Nicolaisen, emma, Johannes Schindelin

From: "Johannes Schindelin" <johannes.schindelin@gmx.de>
> Hi Roberto,
>
> On 2015-05-22 11:42, Johannes Schindelin wrote:
>
>> On 2015-05-22 10:33, Roberto Tyley wrote:
>>> On Tuesday, 19 May 2015, Stefan Beller <sbeller@google.com> wrote:
>>>> On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
>>>> <rcdailey.lists@gmail.com> wrote:
>>>> > How do you send your patches inline?
>>> [snip]
>>>> This workflow discussion was a topic at the GitMerge2015 
>>>> conference,
>>>> and there are essentially 2 groups, those who know how to send 
>>>> email
>>>> and those who complain about it. A solution was agreed on by nearly 
>>>> all
>>>> of the contributors. It would be awesome to have a git-to-email 
>>>> proxy,
>>>> such that you could do a git push <proxy> 
>>>> master:refs/for/mailinglist
>>>> and this proxy would convert the push into sending patch series to 
>>>> the
>>>> mailing list. It could even convert the following discussion back 
>>>> into
>>>> comments (on Github?) but as a first step we'd want to try out a 
>>>> one
>>>> way proxy.
>>>>
>>>> Unfortunately nobody stepped up to actually do the work, yet :(
>>>
>>>
>>> Hello, I'm stepping up to do that work :) Or at least, I'm 
>>> implementing a
>>> one-way GitHub PR -> Mailing list tool, called submitGit:
>>>
>>> https://submitgit.herokuapp.com/
>>
>> Wow!!!
>>
>> I will make sure to test it with a couple of patches I want to submit 
>> anyway.
>
> I just tried this with https://github.com/git/git/pull/139 and would 
> like to tell you about two wishes I had immediately:
>
> - If the author of a patch I am submitting is not myself, could 
> submitGit maybe add that `From: ` line at the top of the mail?
> - The patch series is sent without a cover letter, but it would be 
> *really* great if a path series consisting of more than one patch 
> could have the initial comment of the Pull Request as a cover letter, 
> with the link to the original Pull Request at the bottom? This would 
> also be the mail to use in the "In-reply-yo" header instead of the 
> first patch.
>
> Thanks so much!
> Dscho


A separate request would be to be able to use PRs that are for forks of 
git/git, such as msysgit etc. (i.e. have a common --root), which would 
help in the upstreaming of some changes.


I ask because I just logged in and my preparatory PR318 
(https://github.com/msysgit/git/pull/318) for rejuvenating the 
msvc-build system wasn't listed, probably because of the forking.
--
Philip 

^ permalink raw reply	[relevance 2%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-22 17:05  4%       ` Stefan Beller
@ 2015-05-22 17:26  4%         ` Junio C Hamano
  2015-05-22 17:35  7%         ` Philip Oakley
  1 sibling, 0 replies; 200+ results
From: Junio C Hamano @ 2015-05-22 17:26 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Philip Oakley, Jonathan Nieder, git@vger.kernel.org, Petr Baudis,
	Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

> On Fri, May 22, 2015 at 7:36 AM, Junio C Hamano <gitster@pobox.com> wrote:
>> Stefan Beller <sbeller@google.com> writes:
>>
>>> On Thu, May 21, 2015 at 1:03 PM, Philip Oakley <philipoakley@iee.org> wrote:
>>>>> +Submodules are not to be confused with remotes, which are meant
>>>>> +mainly for branches of the same project;
>>>>
>>>> This use of 'branches' didn't work for me. "remotes are meant mainly for
>>>> branches of the same project" ?
>>
>> The "branch" in the original is used in a much wider sense than
>> usual branch (i.e. ref/heads/ thing you have locally); it refers to
>> forks of the same project but with a bit of twist.  When you say
>> repository A is a fork of the same project as my local repository,
>> you would give an impression that A is not the authoritative copy of
>> the project.  But you can say my repository and that repository A
>> are branches of the same project, you give zero information as to
>> A's authoritativeness.
>
> While this is correct, I think it is also confusing, because...

Oh, no question about it.  In modern Git parlance, it confuses by
conflating 'branch' (which is local ref/heads/ thing) with something
entirely different.  I wasn't saying "'branch' is correct and we
should keep the description that way".

If you dig ancient list archives, you see Linus and I using 'branch'
to mean "your copy of the project" quite often, and that is likely
where the above phrase originated.  It was one of those "explaining
historical background", nothing more.

I probably should start prefixing all my "explaining historical
background" sentences as such.

>> I do not think this is a great improvement.  You now conflated
>> "repository" to mean "project" in the latter half of the sentence,
>> while you are trying to explain what a "remote repository" is.
>
> That's true.
>>
>> Your copy of git.git is not the same repository as mine; they have
>> different histories.  Both repositories are used to work on the same
>> project.  "submoules are not remotes, which are other repositories
>> of the same project", perhaps?
>
> That makes sense.

Thanks.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-22 17:05  4%       ` Stefan Beller
  2015-05-22 17:26  4%         ` Junio C Hamano
@ 2015-05-22 17:35  7%         ` Philip Oakley
  2015-05-22 17:51  4%           ` Stefan Beller
  1 sibling, 1 reply; 200+ results
From: Philip Oakley @ 2015-05-22 17:35 UTC (permalink / raw)
  To: Stefan Beller, Junio C Hamano
  Cc: Jonathan Nieder, git, Petr Baudis, Heiko Voigt

From: "Stefan Beller" <sbeller@google.com>
> On Fri, May 22, 2015 at 7:36 AM, Junio C Hamano <gitster@pobox.com> 
> wrote:
>> Stefan Beller <sbeller@google.com> writes:
>>
>>> On Thu, May 21, 2015 at 1:03 PM, Philip Oakley 
>>> <philipoakley@iee.org> wrote:
>>>>> +Submodules are not to be confused with remotes, which are meant
>>>>> +mainly for branches of the same project;
>>>>
>>>> This use of 'branches' didn't work for me. "remotes are meant 
>>>> mainly for
>>>> branches of the same project" ?
>>
>> The "branch" in the original is used in a much wider sense than
>> usual branch (i.e. ref/heads/ thing you have locally); it refers to
>> forks of the same project but with a bit of twist.  When you say
>> repository A is a fork of the same project as my local repository,
>> you would give an impression that A is not the authoritative copy of
>> the project.  But you can say my repository and that repository A
>> are branches of the same project, you give zero information as to
>> A's authoritativeness.
>
> While this is correct, I think it is also confusing, because 'branch'
> is a command which deals with local branches only in my perception
> To deal with remote branches you need to use the commands
> {remote, fetch, pull}.
>
> So when someone mentions "branch" I need to think of local operations
> in one repository and not on different distributed histories.
>

If we are having difficulties defining a "remote" here (its not defined 
in gitglossary.txt anyway), why not simply put a full stop (period) 
after the "Submodules are not to be confused with remotes.", and bypass 
the problem, avoiding digging the hole deeper.

>>
>>>     Submodules should not be confused with remote repositories, 
>>> which are
>>>     meant to track the same repository, just at another location; 
>>> ...
>>
>> I do not think this is a great improvement.  You now conflated
>> "repository" to mean "project" in the latter half of the sentence,
>> while you are trying to explain what a "remote repository" is.
>
> That's true.
>
>>
>> Your copy of git.git is not the same repository as mine; they have
>> different histories.  Both repositories are used to work on the same
>> project.  "submoules are not remotes, which are other repositories
>> of the same project", perhaps?
>
> That makes sense.
>

If maybe that the feature we should pick on is the common root of the 
development between the local and remote repository, and quite distinct 
for the submodule. This allows remotes to be on the same machine, as 
well as distant machines and server.

It is I believe technically possible to have a submodule which is its 
own super project, with and without recursion, but would be very 
atypical, and would belong in the 'don't do that' category 

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-22 17:35  7%         ` Philip Oakley
@ 2015-05-22 17:51  4%           ` Stefan Beller
  2015-05-22 19:47  4%             ` Philip Oakley
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-05-22 17:51 UTC (permalink / raw)
  To: Philip Oakley
  Cc: Junio C Hamano, Jonathan Nieder, git@vger.kernel.org, Petr Baudis,
	Heiko Voigt

On Fri, May 22, 2015 at 10:35 AM, Philip Oakley <philipoakley@iee.org> wrote:
> From: "Stefan Beller" <sbeller@google.com>
>>
>> On Fri, May 22, 2015 at 7:36 AM, Junio C Hamano <gitster@pobox.com> wrote:
>>>
>>> Stefan Beller <sbeller@google.com> writes:
>>>
>>>> On Thu, May 21, 2015 at 1:03 PM, Philip Oakley <philipoakley@iee.org>
>>>> wrote:
>>>>>>
>>>>>> +Submodules are not to be confused with remotes, which are meant
>>>>>> +mainly for branches of the same project;
>>>>>
>>>>>
>>>>> This use of 'branches' didn't work for me. "remotes are meant mainly
>>>>> for
>>>>> branches of the same project" ?
>>>
>>>
>>> The "branch" in the original is used in a much wider sense than
>>> usual branch (i.e. ref/heads/ thing you have locally); it refers to
>>> forks of the same project but with a bit of twist.  When you say
>>> repository A is a fork of the same project as my local repository,
>>> you would give an impression that A is not the authoritative copy of
>>> the project.  But you can say my repository and that repository A
>>> are branches of the same project, you give zero information as to
>>> A's authoritativeness.
>>
>>
>> While this is correct, I think it is also confusing, because 'branch'
>> is a command which deals with local branches only in my perception
>> To deal with remote branches you need to use the commands
>> {remote, fetch, pull}.
>>
>> So when someone mentions "branch" I need to think of local operations
>> in one repository and not on different distributed histories.
>>
>
> If we are having difficulties defining a "remote" here (its not defined in
> gitglossary.txt anyway),

Now that we have a discussion on what remotes are, I'll send a patch for that
as well.

> why not simply put a full stop (period) after the
> "Submodules are not to be confused with remotes.", and bypass the problem,
> avoiding digging the hole deeper.

I think we should dig deeper and point out the differences as it may
not be clear what
the differences are for new comers. Not digging deeper sounds to me like saying

    'git frotz' is not to be confused with 'git bar' FULL STOP AND I
WONT TELL YOU WHY!

which is not helpful. (Why is the documentation pointing out there is
a difference to
that other command/concept, but not saying what is different?)

>
>>>
>>>>     Submodules should not be confused with remote repositories, which
>>>> are
>>>>     meant to track the same repository, just at another location; ...
>>>
>>>
>>> I do not think this is a great improvement.  You now conflated
>>> "repository" to mean "project" in the latter half of the sentence,
>>> while you are trying to explain what a "remote repository" is.
>>
>>
>> That's true.
>>
>>>
>>> Your copy of git.git is not the same repository as mine; they have
>>> different histories.  Both repositories are used to work on the same
>>> project.  "submoules are not remotes, which are other repositories
>>> of the same project", perhaps?
>>
>>
>> That makes sense.
>>
>
> If maybe that the feature we should pick on is the common root of the
> development between the local and remote repository, and quite distinct for
> the submodule. This allows remotes to be on the same machine, as well as
> distant machines and server.

I don't think this is actually true for all remotes. Think of shallow clones
(they have no root or a different root) or even subtrees which are pulled
in via a remotes?

The main thing about remotes is "not being here" (as in "part of this
repository". As you point out it can be nearby in the local fs or even on
another machine, or in the cloud)

>
> It is I believe technically possible to have a submodule which is its own
> super project, with and without recursion, but would be very atypical, and
> would belong in the 'don't do that' category

^ permalink raw reply	[relevance 4%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  @ 2015-05-22 19:23  4%     ` Stefan Beller
  2015-05-22 19:59  4%       ` Johannes Schindelin
  2015-05-23 14:29  4%       ` Matthieu Moy
  0 siblings, 2 replies; 200+ results
From: Stefan Beller @ 2015-05-22 19:23 UTC (permalink / raw)
  To: Philip Oakley
  Cc: Junio C Hamano, Roberto Tyley, Robert Dailey, Heiko Voigt,
	Johannes Schindelin, Jens Lehmann, Git, Thomas Ferris Nicolaisen,
	emma

Ok, I am trying it out now, all I have left is

    Register your email address
    (stefanbeller@googlemail.com)
    with submitGit's Amazon SES
    account in order for it to send
    emails from you.

So first of all:
Where do I find the Amazon SES account for submitGit, to register
my email with?

Also can I change the email in the process or change it before?

Thanks,
Stefan

^ permalink raw reply	[relevance 4%]

* [PATCH] submodule documentation: Reorder introductory paragraphs
@ 2015-05-22 19:38 23% Stefan Beller
  2015-05-22 21:18  4% ` Philip Oakley
  2015-05-25 22:00  6% ` Junio C Hamano
  0 siblings, 2 replies; 200+ results
From: Stefan Beller @ 2015-05-22 19:38 UTC (permalink / raw)
  To: gitster; +Cc: philipoakley, jrnieder, git, hvoigt, Stefan Beller

It's better to start the man page with a description of what submodules
actually are instead of saying what they are not.

Reorder the paragraphs such that
the first short paragraph introduces the submodule concept,
the second paragraph highlights the usage of the submodule command,
the third paragraph giving background information,
and finally the fourth paragraph discusing alternatives such
as subtrees and remotes, which we don't want to be confused with.

This ordering deepens the knowledge on submodules with each paragraph.
First the basic questions like "How/what" will be answered, while the
underlying concepts will be taught at a later time.

Making sure it is not confused with subtrees and remotes is not really
enhancing knowledge of submodules itself, but rather painting the big
picture of git concepts, so you could also argue to have it as the second
paragraph. Personally I think this may confuse readers, specially
newcomers though.

Additionally to reordering the paragraphs, they have been slightly
reworded.

Signed-off-by: Stefan Beller <sbeller@google.com>
---

For now I used a part of Junios suggestion
    Submodules are not to be confused with remotes, which are other
    repositories of the same project;
    
I like the "are not to be confused" part, as they warn the reader
that there will be a paragraph not as concise but touching other
commands and topics.

 Documentation/git-submodule.txt | 50 ++++++++++++++++++-----------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 2c25916..d126c86 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -25,22 +25,17 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Submodules allow foreign repositories to be embedded within
-a dedicated subdirectory of the source tree, always pointed
-at a particular commit.
+This command will inspect, update and manage submodules.
 
-They are not to be confused with remotes, which are meant mainly
-for branches of the same project; submodules are meant for
-different projects you would like to make part of your source tree,
-while the history of the two projects still stays completely
-independent and you cannot modify the contents of the submodule
-from within the main project.
-If you want to merge the project histories and want to treat the
-aggregated whole as a single project from then on, you may want to
-add a remote for the other project and use the 'subtree' merge strategy,
-instead of treating the other project as a submodule. Directories
-that come from both projects can be cloned and checked out as a whole
-if you choose to go that route.
+Submodules allow you to keep another Git repository in a subdirectory
+of your repository. The other repository has its own history, which does not
+interfere with the history of the current repository. This can be used to
+have external dependencies such as libraries for example.
+
+When cloning or pulling a repository containing submodules however,
+these will not be checked out by default; the 'init' and 'update'
+subcommands will maintain submodules checked out and at
+appropriate revision in your working tree.
 
 Submodules are composed from a so-called `gitlink` tree entry
 in the main repository that refers to a particular commit object
@@ -51,19 +46,18 @@ describes the default URL the submodule shall be cloned from.
 The logical name can be used for overriding this URL within your
 local repository configuration (see 'submodule init').
 
-This command will manage the tree entries and contents of the
-gitmodules file for you, as well as inspect the status of your
-submodules and update them.
-When adding a new submodule to the tree, the 'add' subcommand
-is to be used.  However, when pulling a tree containing submodules,
-these will not be checked out by default;
-the 'init' and 'update' subcommands will maintain submodules
-checked out and at appropriate revision in your working tree.
-You can briefly inspect the up-to-date status of your submodules
-using the 'status' subcommand and get a detailed overview of the
-difference between the index and checkouts using the 'summary'
-subcommand.
-
+Submodules are not to be confused with remotes, which are other
+repositories of the same project; submodules are meant for
+different projects you would like to make part of your source tree,
+while the history of the two projects still stays completely
+independent and you cannot modify the contents of the submodule
+from within the main project.
+If you want to merge the project histories and want to treat the
+aggregated whole as a single project from then on, you may want to
+add a remote for the other project and use the 'subtree' merge strategy,
+instead of treating the other project as a submodule. Directories
+that come from both projects can be cloned and checked out as a whole
+if you choose to go that route.
 
 COMMANDS
 --------
-- 
2.4.1.233.g3f9b614.dirty

^ permalink raw reply related	[relevance 23%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-22 17:51  4%           ` Stefan Beller
@ 2015-05-22 19:47  4%             ` Philip Oakley
  0 siblings, 0 replies; 200+ results
From: Philip Oakley @ 2015-05-22 19:47 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Junio C Hamano, Jonathan Nieder, git, Petr Baudis, Heiko Voigt

From: "Stefan Beller" <sbeller@google.com>
> On Fri, May 22, 2015 at 10:35 AM, Philip Oakley <philipoakley@iee.org> 
> wrote:
>> From: "Stefan Beller" <sbeller@google.com>
>>>
>>> On Fri, May 22, 2015 at 7:36 AM, Junio C Hamano <gitster@pobox.com> 
>>> wrote:
>>>>
>>>> Stefan Beller <sbeller@google.com> writes:
>>>>
>>>>> On Thu, May 21, 2015 at 1:03 PM, Philip Oakley 
>>>>> <philipoakley@iee.org>
>>>>> wrote:
>>>>>>>
>>>>>>> +Submodules are not to be confused with remotes, which are meant
>>>>>>> +mainly for branches of the same project;
>>>>>>
>>>>>>
>>>>>> This use of 'branches' didn't work for me. "remotes are meant 
>>>>>> mainly
>>>>>> for
>>>>>> branches of the same project" ?
>>>>
>>>>
>>>> The "branch" in the original is used in a much wider sense than
>>>> usual branch (i.e. ref/heads/ thing you have locally); it refers to
>>>> forks of the same project but with a bit of twist.  When you say
>>>> repository A is a fork of the same project as my local repository,
>>>> you would give an impression that A is not the authoritative copy 
>>>> of
>>>> the project.  But you can say my repository and that repository A
>>>> are branches of the same project, you give zero information as to
>>>> A's authoritativeness.
>>>
>>>
>>> While this is correct, I think it is also confusing, because 
>>> 'branch'
>>> is a command which deals with local branches only in my perception
>>> To deal with remote branches you need to use the commands
>>> {remote, fetch, pull}.
>>>
>>> So when someone mentions "branch" I need to think of local 
>>> operations
>>> in one repository and not on different distributed histories.
>>>
>>
>> If we are having difficulties defining a "remote" here (its not 
>> defined in
>> gitglossary.txt anyway),
>
> Now that we have a discussion on what remotes are, I'll send a patch 
> for that
> as well.
>
>> why not simply put a full stop (period) after the
>> "Submodules are not to be confused with remotes.", and bypass the 
>> problem,
>> avoiding digging the hole deeper.
>
> I think we should dig deeper and point out the differences as it may
> not be clear what
> the differences are for new comers. Not digging deeper sounds to me 
> like saying
>
>    'git frotz' is not to be confused with 'git bar' FULL STOP AND I
> WONT TELL YOU WHY!

Hi Stefan,
This was more of a case of "simply a full stop, 'cos I can't easily tell 
you why" ;-).  I've seen too many work situations (*) where colleagues 
just dig deeper when they should stop digging, hence the note. It may be 
that the style of reason could be changed. This is the final 
introductory paragraph and was being pushed down partly because of this 
problem (explaining things by saying what its not).

(*) The usual phrase in a report would be "A moments thought will show 
that ..." for those concepts that would take two pages to explain and 
would still be misunderstood by the unthinking folks.

That all said, if a nice well understood explanatory phrase can be found 
then I'm all for it.

>
> which is not helpful. (Why is the documentation pointing out there is
> a difference to
> that other command/concept, but not saying what is different?)
>
>>
>>>>
>>>>>     Submodules should not be confused with remote repositories, 
>>>>> which
>>>>> are
>>>>>     meant to track the same repository, just at another location; 
>>>>> ...
>>>>
>>>>
>>>> I do not think this is a great improvement.  You now conflated
>>>> "repository" to mean "project" in the latter half of the sentence,
>>>> while you are trying to explain what a "remote repository" is.
>>>
>>>
>>> That's true.
>>>
>>>>
>>>> Your copy of git.git is not the same repository as mine; they have
>>>> different histories.  Both repositories are used to work on the 
>>>> same
>>>> project.  "submoules are not remotes, which are other repositories
>>>> of the same project", perhaps?
>>>
>>>
>>> That makes sense.
>>>
>>
>> If maybe that the feature we should pick on is the common root of the
>> development between the local and remote repository, and quite 
>> distinct for
>> the submodule. This allows remotes to be on the same machine, as well 
>> as
>> distant machines and server.
>
> I don't think this is actually true for all remotes. Think of shallow 
> clones
> (they have no root or a different root) or even subtrees which are 
> pulled
> in via a remotes?

I'd avoided mentioning that potential explanation mud-hole on the same 
basis that it would be hard.

>
> The main thing about remotes is "not being here" (as in "part of this
> repository". As you point out it can be nearby in the local fs or even 
> on
> another machine, or in the cloud)
>
>>
>> It is I believe technically possible to have a submodule which is its 
>> own
>> super project, with and without recursion, but would be very 
>> atypical, and
>> would belong in the 'don't do that' category
>
regards
Philip 

^ permalink raw reply	[relevance 4%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22 17:14  2%     ` Philip Oakley
@ 2015-05-22 19:58  2%       ` Johannes Schindelin
  2015-05-22 21:35  2%         ` Philip Oakley
  0 siblings, 1 reply; 200+ results
From: Johannes Schindelin @ 2015-05-22 19:58 UTC (permalink / raw)
  To: Philip Oakley
  Cc: Roberto Tyley, Stefan Beller, Robert Dailey, Heiko Voigt,
	Jens Lehmann, Git, Thomas Ferris Nicolaisen, emma

Hi,

On 2015-05-22 19:14, Philip Oakley wrote:
> From: "Johannes Schindelin" <johannes.schindelin@gmx.de>

>> On 2015-05-22 11:42, Johannes Schindelin wrote:
>>
>>> On 2015-05-22 10:33, Roberto Tyley wrote:
>>>> On Tuesday, 19 May 2015, Stefan Beller <sbeller@google.com> wrote:
>>>>> On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
>>>>> <rcdailey.lists@gmail.com> wrote:
>>>>> > How do you send your patches inline?
>>>> [snip]
>>>>> This workflow discussion was a topic at the GitMerge2015 conference,
>>>>> and there are essentially 2 groups, those who know how to send email
>>>>> and those who complain about it. A solution was agreed on by nearly all
>>>>> of the contributors. It would be awesome to have a git-to-email proxy,
>>>>> such that you could do a git push <proxy> master:refs/for/mailinglist
>>>>> and this proxy would convert the push into sending patch series to the
>>>>> mailing list. It could even convert the following discussion back into
>>>>> comments (on Github?) but as a first step we'd want to try out a one
>>>>> way proxy.
>>>>>
>>>>> Unfortunately nobody stepped up to actually do the work, yet :(
>>>>
>>>>
>>>> Hello, I'm stepping up to do that work :) Or at least, I'm implementing a
>>>> one-way GitHub PR -> Mailing list tool, called submitGit:
>>>>
>>>> https://submitgit.herokuapp.com/
>>>
>>> Wow!!!
>>>
>>> I will make sure to test it with a couple of patches I want to submit anyway.
>>
>> I just tried this with https://github.com/git/git/pull/139 and would like to tell you about two wishes I had immediately:
>>
>> - If the author of a patch I am submitting is not myself, could submitGit maybe add that `From: ` line at the top of the mail?
>> - The patch series is sent without a cover letter, but it would be *really* great if a path series consisting of more than one patch could have the initial comment of the Pull Request as a cover letter, with the link to the original Pull Request at the bottom? This would also be the mail to use in the "In-reply-yo" header instead of the first patch.
>>
>> Thanks so much!
>> Dscho
> 
> 
> A separate request would be to be able to use PRs that are for forks
> of git/git, such as msysgit etc. (i.e. have a common --root), which
> would help in the upstreaming of some changes.
> 
> 
> I ask because I just logged in and my preparatory PR318
> (https://github.com/msysgit/git/pull/318) for rejuvenating the
> msvc-build system wasn't listed, probably because of the forking.

You can easily change what upstream your PR is intended for. For example, I made my PR from my own Git fork (which is based on msysgit/git) relative to git/git by entering the URL:

https://github.com/git/git/compare/next...dscho:non-win-fixes?expand=true

So there is no real need for anything extra: the only git.git project that requires emails (that I am aware of) for the submission process is git/git.

Ciao,
Dscho

^ permalink raw reply	[relevance 2%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22 19:23  4%     ` Stefan Beller
@ 2015-05-22 19:59  4%       ` Johannes Schindelin
  2015-05-22 20:04  2%         ` Junio C Hamano
  2015-05-23 14:29  4%       ` Matthieu Moy
  1 sibling, 1 reply; 200+ results
From: Johannes Schindelin @ 2015-05-22 19:59 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Philip Oakley, Junio C Hamano, Roberto Tyley, Robert Dailey,
	Heiko Voigt, Jens Lehmann, Git, Thomas Ferris Nicolaisen, emma

Hi Stefan,

On 2015-05-22 21:23, Stefan Beller wrote:
> Ok, I am trying it out now, all I have left is
> 
>     Register your email address
>     (stefanbeller@googlemail.com)
>     with submitGit's Amazon SES
>     account in order for it to send
>     emails from you.
> 
> So first of all:
> Where do I find the Amazon SES account for submitGit, to register
> my email with?
> 
> Also can I change the email in the process or change it before?

FWIW I did not have to register my email. All I needed to do was to give submitGit permissions to read my personal email address and my public repositories.

Ciao,
Dscho

^ permalink raw reply	[relevance 4%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22 19:59  4%       ` Johannes Schindelin
@ 2015-05-22 20:04  2%         ` Junio C Hamano
  2015-05-22 20:44  4%           ` Stefan Beller
  2015-05-23  9:11  2%           ` Johannes Schindelin
  0 siblings, 2 replies; 200+ results
From: Junio C Hamano @ 2015-05-22 20:04 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Stefan Beller, Philip Oakley, Roberto Tyley, Robert Dailey,
	Heiko Voigt, Jens Lehmann, Git, Thomas Ferris Nicolaisen, emma

On Fri, May 22, 2015 at 12:59 PM, Johannes Schindelin
<johannes.schindelin@gmx.de> wrote:
>
> On 2015-05-22 21:23, Stefan Beller wrote:
>>
>> So first of all:
>> Where do I find the Amazon SES account for submitGit, to register
>> my email with?
>>
>> Also can I change the email in the process or change it before?
>
> FWIW I did not have to register my email. All I needed to do was to give submitGit
> permissions to read my personal email address and my public repositories.

Hmph, I was asked way more than that (especially, read and write access).
Does the site ask different authorizations depending on who you are?

^ permalink raw reply	[relevance 2%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22 20:04  2%         ` Junio C Hamano
@ 2015-05-22 20:44  4%           ` Stefan Beller
  2015-05-23  9:11  2%           ` Johannes Schindelin
  1 sibling, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-22 20:44 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johannes Schindelin, Philip Oakley, Roberto Tyley, Robert Dailey,
	Heiko Voigt, Jens Lehmann, Git, Thomas Ferris Nicolaisen, emma

On Fri, May 22, 2015 at 1:04 PM, Junio C Hamano <gitster@pobox.com> wrote:
> On Fri, May 22, 2015 at 12:59 PM, Johannes Schindelin
> <johannes.schindelin@gmx.de> wrote:
>>
>> On 2015-05-22 21:23, Stefan Beller wrote:
>>>
>>> So first of all:
>>> Where do I find the Amazon SES account for submitGit, to register
>>> my email with?
>>>
>>> Also can I change the email in the process or change it before?
>>
>> FWIW I did not have to register my email. All I needed to do was to give submitGit
>> permissions to read my personal email address and my public repositories.
>
> Hmph, I was asked way more than that (especially, read and write access).
> Does the site ask different authorizations depending on who you are?

I was also asked for read/write on my copy of git, but as I am not
the maintainer nor trusted in any way, I figured that's ok.
I still have my local copy which would notice any changes on git push.

The question I was asking was the only thing I could not answer
or decide for myself.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-22 19:38 23% [PATCH] submodule documentation: Reorder introductory paragraphs Stefan Beller
@ 2015-05-22 21:18  4% ` Philip Oakley
  2015-05-25 22:00  6% ` Junio C Hamano
  1 sibling, 0 replies; 200+ results
From: Philip Oakley @ 2015-05-22 21:18 UTC (permalink / raw)
  To: Stefan Beller, gitster; +Cc: jrnieder, git, hvoigt, Stefan Beller

From: "Stefan Beller" <sbeller@google.com>
> It's better to start the man page with a description of what 
> submodules
> actually are instead of saying what they are not.
>
> Reorder the paragraphs such that
> the first short paragraph introduces the submodule concept,
> the second paragraph highlights the usage of the submodule command,
> the third paragraph giving background information,
> and finally the fourth paragraph discusing alternatives such
> as subtrees and remotes, which we don't want to be confused with.
>
> This ordering deepens the knowledge on submodules with each paragraph.
> First the basic questions like "How/what" will be answered, while the
> underlying concepts will be taught at a later time.
>
> Making sure it is not confused with subtrees and remotes is not really
> enhancing knowledge of submodules itself, but rather painting the big
> picture of git concepts, so you could also argue to have it as the 
> second
> paragraph. Personally I think this may confuse readers, specially
> newcomers though.
>
> Additionally to reordering the paragraphs, they have been slightly
> reworded.
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>
> For now I used a part of Junios suggestion
>    Submodules are not to be confused with remotes, which are other
>    repositories of the same project;
>
> I like the "are not to be confused" part, as they warn the reader
> that there will be a paragraph not as concise but touching other
> commands and topics.
>
> Documentation/git-submodule.txt | 50 
> ++++++++++++++++++-----------------------
> 1 file changed, 22 insertions(+), 28 deletions(-)
>
> diff --git a/Documentation/git-submodule.txt 
> b/Documentation/git-submodule.txt
> index 2c25916..d126c86 100644
> --- a/Documentation/git-submodule.txt
> +++ b/Documentation/git-submodule.txt
> @@ -25,22 +25,17 @@ SYNOPSIS
>
> DESCRIPTION
> -----------
> -Submodules allow foreign repositories to be embedded within
> -a dedicated subdirectory of the source tree, always pointed
> -at a particular commit.
> +This command will inspect, update and manage submodules.
>
> -They are not to be confused with remotes, which are meant mainly
> -for branches of the same project; submodules are meant for
> -different projects you would like to make part of your source tree,
> -while the history of the two projects still stays completely
> -independent and you cannot modify the contents of the submodule
> -from within the main project.
> -If you want to merge the project histories and want to treat the
> -aggregated whole as a single project from then on, you may want to
> -add a remote for the other project and use the 'subtree' merge 
> strategy,
> -instead of treating the other project as a submodule. Directories
> -that come from both projects can be cloned and checked out as a whole
> -if you choose to go that route.
> +Submodules allow you to keep another Git repository in a subdirectory
> +of your repository. The other repository has its own history, which 
> does not
> +interfere with the history of the current repository. This can be 
> used to
> +have external dependencies such as libraries for example.
> +
> +When cloning or pulling a repository containing submodules however,
> +these will not be checked out by default; the 'init' and 'update'
> +subcommands will maintain submodules checked out and at
> +appropriate revision in your working tree.
>
> Submodules are composed from a so-called `gitlink` tree entry
> in the main repository that refers to a particular commit object
> @@ -51,19 +46,18 @@ describes the default URL the submodule shall be 
> cloned from.
> The logical name can be used for overriding this URL within your
> local repository configuration (see 'submodule init').
>
> -This command will manage the tree entries and contents of the
> -gitmodules file for you, as well as inspect the status of your
> -submodules and update them.
> -When adding a new submodule to the tree, the 'add' subcommand
> -is to be used.  However, when pulling a tree containing submodules,
> -these will not be checked out by default;
> -the 'init' and 'update' subcommands will maintain submodules
> -checked out and at appropriate revision in your working tree.
> -You can briefly inspect the up-to-date status of your submodules
> -using the 'status' subcommand and get a detailed overview of the
> -difference between the index and checkouts using the 'summary'
> -subcommand.
> -
> +Submodules are not to be confused with remotes, which are other
> +repositories of the same project;

I said (22 May 2015 20:47):
"if a nice well understood explanatory phrase can be found " - I'm happy 
with yours. Many thanks

>                                        submodules are meant for
> +different projects you would like to make part of your source tree,
> +while the history of the two projects still stays completely
> +independent and you cannot modify the contents of the submodule
> +from within the main project.
> +If you want to merge the project histories and want to treat the
> +aggregated whole as a single project from then on, you may want to
> +add a remote for the other project and use the 'subtree' merge 
> strategy,
> +instead of treating the other project as a submodule. Directories
> +that come from both projects can be cloned and checked out as a whole
> +if you choose to go that route.
>
> COMMANDS
> --------
> -- 
> 2.4.1.233.g3f9b614.dirty
>
> --
Philip 

^ permalink raw reply	[relevance 4%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22 19:58  2%       ` Johannes Schindelin
@ 2015-05-22 21:35  2%         ` Philip Oakley
  0 siblings, 0 replies; 200+ results
From: Philip Oakley @ 2015-05-22 21:35 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Roberto Tyley, Stefan Beller, Robert Dailey, Heiko Voigt,
	Jens Lehmann, Git, Thomas Ferris Nicolaisen, emma

From: "Johannes Schindelin" <johannes.schindelin@gmx.de>
> Hi,
>
> On 2015-05-22 19:14, Philip Oakley wrote:
>> From: "Johannes Schindelin" <johannes.schindelin@gmx.de>
>
>>> On 2015-05-22 11:42, Johannes Schindelin wrote:
>>>
>>>> On 2015-05-22 10:33, Roberto Tyley wrote:
>>>>> On Tuesday, 19 May 2015, Stefan Beller <sbeller@google.com> wrote:
>>>>>> On Tue, May 19, 2015 at 12:29 PM, Robert Dailey
>>>>>> <rcdailey.lists@gmail.com> wrote:
>>>>>> > How do you send your patches inline?
>>>>> [snip]
>>>>>> This workflow discussion was a topic at the GitMerge2015 
>>>>>> conference,
>>>>>> and there are essentially 2 groups, those who know how to send 
>>>>>> email
>>>>>> and those who complain about it. A solution was agreed on by 
>>>>>> nearly all
>>>>>> of the contributors. It would be awesome to have a git-to-email 
>>>>>> proxy,
>>>>>> such that you could do a git push <proxy> 
>>>>>> master:refs/for/mailinglist
>>>>>> and this proxy would convert the push into sending patch series 
>>>>>> to the
>>>>>> mailing list. It could even convert the following discussion back 
>>>>>> into
>>>>>> comments (on Github?) but as a first step we'd want to try out a 
>>>>>> one
>>>>>> way proxy.
>>>>>>
>>>>>> Unfortunately nobody stepped up to actually do the work, yet :(
>>>>>
>>>>>
>>>>> Hello, I'm stepping up to do that work :) Or at least, I'm 
>>>>> implementing a
>>>>> one-way GitHub PR -> Mailing list tool, called submitGit:
>>>>>
>>>>> https://submitgit.herokuapp.com/
>>>>
>>>> Wow!!!
>>>>
>>>> I will make sure to test it with a couple of patches I want to 
>>>> submit anyway.
>>>
>>> I just tried this with https://github.com/git/git/pull/139 and would 
>>> like to tell you about two wishes I had immediately:
>>>
>>> - If the author of a patch I am submitting is not myself, could 
>>> submitGit maybe add that `From: ` line at the top of the mail?
>>> - The patch series is sent without a cover letter, but it would be 
>>> *really* great if a path series consisting of more than one patch 
>>> could have the initial comment of the Pull Request as a cover 
>>> letter, with the link to the original Pull Request at the bottom? 
>>> This would also be the mail to use in the "In-reply-yo" header 
>>> instead of the first patch.
>>>
>>> Thanks so much!
>>> Dscho
>>
>>
>> A separate request would be to be able to use PRs that are for forks
>> of git/git, such as msysgit etc. (i.e. have a common --root), which
>> would help in the upstreaming of some changes.
>>
>>
>> I ask because I just logged in and my preparatory PR318
>> (https://github.com/msysgit/git/pull/318) for rejuvenating the
>> msvc-build system wasn't listed, probably because of the forking.
>
> You can easily change what upstream your PR is intended for. For 
> example, I made my PR from my own Git fork (which is based on 
> msysgit/git) relative to git/git by entering the URL:
>
> https://github.com/git/git/compare/next...dscho:non-win-fixes?expand=true
>
> So there is no real need for anything extra: the only git.git project 
> that requires emails (that I am aware of) for the submission process 
> is git/git.
>
> Ciao,
> Dscho
>
Do I read you right.. That it's necessary to create a PR on git/git 
before submitGit can be used.

And that if I already have a PR which goes back to an alternate fork 
(e.g. my example), then I must move or duplicate that PR onto git/git 
before it can be used.

[I find a few UI issues with the github interface in that I'd hoped to 
be able to see which outgoing PRs I have from my own fork but I can't 
see how to do that]

regards

Philip 

^ permalink raw reply	[relevance 2%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22 20:04  2%         ` Junio C Hamano
  2015-05-22 20:44  4%           ` Stefan Beller
@ 2015-05-23  9:11  2%           ` Johannes Schindelin
  1 sibling, 0 replies; 200+ results
From: Johannes Schindelin @ 2015-05-23  9:11 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Stefan Beller, Philip Oakley, Roberto Tyley, Robert Dailey,
	Heiko Voigt, Jens Lehmann, Git, Thomas Ferris Nicolaisen, emma

Hi Junio,

On 2015-05-22 22:04, Junio C Hamano wrote:
> On Fri, May 22, 2015 at 12:59 PM, Johannes Schindelin
> <johannes.schindelin@gmx.de> wrote:
>>
>> On 2015-05-22 21:23, Stefan Beller wrote:
>>>
>>> So first of all:
>>> Where do I find the Amazon SES account for submitGit, to register
>>> my email with?
>>>
>>> Also can I change the email in the process or change it before?
>>
>> FWIW I did not have to register my email. All I needed to do was to give submitGit
>> permissions to read my personal email address and my public repositories.
> 
> Hmph, I was asked way more than that (especially, read and write access).
> Does the site ask different authorizations depending on who you are?

Well, I did not try to send to the mailing list yet. Maybe that's the difference? Or maybe it is because I just registered with Heroku before...

Ciao,
Dscho

^ permalink raw reply	[relevance 2%]

* Re: [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs")
  2015-05-22 19:23  4%     ` Stefan Beller
  2015-05-22 19:59  4%       ` Johannes Schindelin
@ 2015-05-23 14:29  4%       ` Matthieu Moy
  1 sibling, 0 replies; 200+ results
From: Matthieu Moy @ 2015-05-23 14:29 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Philip Oakley, Junio C Hamano, Roberto Tyley, Robert Dailey,
	Heiko Voigt, Johannes Schindelin, Jens Lehmann, Git,
	Thomas Ferris Nicolaisen, emma

Stefan Beller <sbeller@google.com> writes:

> Ok, I am trying it out now, all I have left is
>
>     Register your email address
>     (stefanbeller@googlemail.com)
>     with submitGit's Amazon SES
>     account in order for it to send
>     emails from you.
>
> So first of all:
> Where do I find the Amazon SES account for submitGit, to register
> my email with?
>
> Also can I change the email in the process or change it before?

I was confused at the same point, but at the top of the screen showing
this message, there was a link to do this registration. I was just not
looking at the right place.

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

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-22 19:38 23% [PATCH] submodule documentation: Reorder introductory paragraphs Stefan Beller
  2015-05-22 21:18  4% ` Philip Oakley
@ 2015-05-25 22:00  6% ` Junio C Hamano
  2015-05-26 17:53  7%   ` Stefan Beller
  1 sibling, 1 reply; 200+ results
From: Junio C Hamano @ 2015-05-25 22:00 UTC (permalink / raw)
  To: Stefan Beller; +Cc: philipoakley, jrnieder, git, hvoigt

Stefan Beller <sbeller@google.com> writes:

>  DESCRIPTION
>  -----------
> +This command will inspect, update and manage submodules.
>  
> +Submodules allow you to keep another Git repository in a subdirectory
> +of your repository. The other repository has its own history,...

The first line somehow bothered me, so I took a random sample of
commands I often use:

    git log
       Shows the commit logs.

    git show
       Shows one or more objects (blobs, trees, tags and commits).

    git commit
       Stores the current contents of the index in a new commit along with a
       log message from the user describing the changes.

    git diff
       Show changes between the working tree and the index or a tree, changes
       between the index and a tree, changes between two trees, changes
       between two blob objects, or changes between two files on disk.

    git push
       Updates remote refs using local refs, while sending objects necessary
       to complete the given refs.

I _think_ what bothered me was "This command" (drawing the reaction
"eh, what other command are you going to talk about in the help page
for this command?").  Perhaps

    Inspects, updates and manages submodules.

may match the style of other help pages better.

On the other hand, I probably would not have felt such a strong
"strangeness" if it were described like this:

    This command can help you inspect, update, and manage
    submodules.

I haven't analized it enough to say why it is, but I suspect it has
something to do with (my own) perception that "git submodule" is not
very essential to do any of these things (i.e. .gitmodules is a very
simple text file), but is primarily a helpful wrapper.

The description of "git config", on which I have a similar
perception, seem to match ;-)

    git config
       You can query/set/replace/unset options with this command.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-25 22:00  6% ` Junio C Hamano
@ 2015-05-26 17:53  7%   ` Stefan Beller
  2015-05-26 21:58  7%     ` Heiko Voigt
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-05-26 17:53 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Philip Oakley, Jonathan Nieder, git@vger.kernel.org, Heiko Voigt

On Mon, May 25, 2015 at 3:00 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>>  DESCRIPTION
>>  -----------
>> +This command will inspect, update and manage submodules.
>>
>> +Submodules allow you to keep another Git repository in a subdirectory
>> +of your repository. The other repository has its own history,...
>
> The first line somehow bothered me, so I took a random sample of
> commands I often use:
>
>     git log
>        Shows the commit logs.
>
>     git show
>        Shows one or more objects (blobs, trees, tags and commits).
>
>     git commit
>        Stores the current contents of the index in a new commit along with a
>        log message from the user describing the changes.
>
>     git diff
>        Show changes between the working tree and the index or a tree, changes
>        between the index and a tree, changes between two trees, changes
>        between two blob objects, or changes between two files on disk.
>
>     git push
>        Updates remote refs using local refs, while sending objects necessary
>        to complete the given refs.
>
> I _think_ what bothered me was "This command" (drawing the reaction
> "eh, what other command are you going to talk about in the help page
> for this command?").  Perhaps
>
>     Inspects, updates and manages submodules.
>
> may match the style of other help pages better.

Sounds much better than my patch.

>
> On the other hand, I probably would not have felt such a strong
> "strangeness" if it were described like this:
>
>     This command can help you inspect, update, and manage
>     submodules.
>
> I haven't analized it enough to say why it is, but I suspect it has
> something to do with (my own) perception that "git submodule" is not
> very essential to do any of these things (i.e. .gitmodules is a very
> simple text file), but is primarily a helpful wrapper.

My perception is that the submodule man page similar to the subtree
man page tries to explain an underlying concept as well. The other man
pages you quoted don't do that as the concepts are explained elsewhere(?)

As a side note: In the Gerrit test suite I use the JGit implementation of
the config command to write out .gitmodules files. So maybe `git submodule`
can be understood as a specialized form of `git config`.

>
> The description of "git config", on which I have a similar
> perception, seem to match ;-)
>
>     git config
>        You can query/set/replace/unset options with this command.
>

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule documentation: Reorder introductory paragraphs
  2015-05-26 17:53  7%   ` Stefan Beller
@ 2015-05-26 21:58  7%     ` Heiko Voigt
  0 siblings, 0 replies; 200+ results
From: Heiko Voigt @ 2015-05-26 21:58 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Junio C Hamano, Philip Oakley, Jonathan Nieder,
	git@vger.kernel.org

On Tue, May 26, 2015 at 10:53:15AM -0700, Stefan Beller wrote:
> On Mon, May 25, 2015 at 3:00 PM, Junio C Hamano <gitster@pobox.com> wrote:
> > Stefan Beller <sbeller@google.com> writes:
> > On the other hand, I probably would not have felt such a strong
> > "strangeness" if it were described like this:
> >
> >     This command can help you inspect, update, and manage
> >     submodules.
> >
> > I haven't analized it enough to say why it is, but I suspect it has
> > something to do with (my own) perception that "git submodule" is not
> > very essential to do any of these things (i.e. .gitmodules is a very
> > simple text file), but is primarily a helpful wrapper.
> 
> My perception is that the submodule man page similar to the subtree
> man page tries to explain an underlying concept as well. The other man
> pages you quoted don't do that as the concepts are explained elsewhere(?)
> 
> As a side note: In the Gerrit test suite I use the JGit implementation of
> the config command to write out .gitmodules files. So maybe `git submodule`
> can be understood as a specialized form of `git config`.

I do not agree here. That view is too limited. Since in the case of e.g. 'git
submodule add‘ it does not only change the .gitmodules file but adds a gitlink
entry to the index, moves the database into .git/modules, ... .

And even though it is currently not doing much more it might in the
future. E.g. it might make sense to add a 'git submodule gc' command
which allows the user to purge unused submodule databases from the
.git/modules directory.

So I would say it is: "a helper" or "a tool" for submodules. Nothing less
nothing more. But on the other hand the same is true for other porcelain
commands like e.g. 'git commit'. If you take a look at gitcore-tutorial
you could also describe it as a wrapper for write-tree, commit-tree and
update-ref to create a commit. Yet the man page says: "Record changes to
the repository".

So I am not sure where to draw the line between wrapper and essential
command. As a user I would see it as quite essential since for adding a
submodule I would need to remember a couple of things:

  * clone the database into .git/modules
  * create the gitlink file
  * checkout the files to the desired directory
  * add the url to the .gitmodules file

So why not go with Junios first suggestion and lets drop the "This
command can help you..." and say: "Inspect, update and manage
submodules".

Cheers Heiko

^ permalink raw reply	[relevance 7%]

* Re: What's cooking in git.git (May 2015, #07; Tue, 26)
  @ 2015-05-26 22:06  2% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-26 22:06 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org

> * sb/submodule-doc-intro (2015-05-22) 1 commit
>  - submodule documentation: reorder introductory paragraphs
>
> What's the doneness of this one???

I'll try again without a "This command will do ..." introduction,
I just did not look into it yet. That said, I was expecting more
bike shedding than usual as it's a documentation only change,
where it's harder to come up with clean and readable text as
compared to code.

^ permalink raw reply	[relevance 2%]

* [PATCHv3] submodule documentation: Reorder introductory paragraphs
@ 2015-05-27 19:48 23% Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-27 19:48 UTC (permalink / raw)
  To: gitster; +Cc: git, philipoakley, hvoigt, Stefan Beller

It's better to start the man page with a description of what submodules
actually are instead of saying what they are not.

Reorder the paragraphs such that
the first short paragraph introduces the submodule concept,
the second paragraph highlights the usage of the submodule command,
the third paragraph giving background information,
and finally the fourth paragraph discusing alternatives such
as subtrees and remotes, which we don't want to be confused with.

This ordering deepens the knowledge on submodules with each paragraph.
First the basic questions like "How/what" will be answered, while the
underlying concepts will be taught at a later time.

Making sure it is not confused with subtrees and remotes is not really
enhancing knowledge of submodules itself, but rather painting the big
picture of git concepts, so you could also argue to have it as the second
paragraph. Personally I think this may confuse readers, specially
newcomers though.

Additionally to reordering the paragraphs, they have been slightly
reworded.

Signed-off-by: Stefan Beller <sbeller@google.com>
---

I think this is the best I can come up with for now.
* It still mentions the remotes as a potential explanation mud-hole, but I feel
  it helps the reader understand submodules a little better.
* We also start with a typical git man page intro (Dropping "This command does ...")

 Documentation/git-submodule.txt | 50 ++++++++++++++++++-----------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 2c25916..2ca1391 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -25,22 +25,17 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Submodules allow foreign repositories to be embedded within
-a dedicated subdirectory of the source tree, always pointed
-at a particular commit.
+Inspects, updates and manages submodules.
 
-They are not to be confused with remotes, which are meant mainly
-for branches of the same project; submodules are meant for
-different projects you would like to make part of your source tree,
-while the history of the two projects still stays completely
-independent and you cannot modify the contents of the submodule
-from within the main project.
-If you want to merge the project histories and want to treat the
-aggregated whole as a single project from then on, you may want to
-add a remote for the other project and use the 'subtree' merge strategy,
-instead of treating the other project as a submodule. Directories
-that come from both projects can be cloned and checked out as a whole
-if you choose to go that route.
+A Submodule allows you to keep another Git repository in a subdirectory
+of your repository. The other repository has its own history, which does not
+interfere with the history of the current repository. This can be used to
+have external dependencies such as third party libraries for example.
+
+When cloning or pulling a repository containing submodules however,
+these will not be checked out by default; the 'init' and 'update'
+subcommands will maintain submodules checked out and at
+appropriate revision in your working tree.
 
 Submodules are composed from a so-called `gitlink` tree entry
 in the main repository that refers to a particular commit object
@@ -51,19 +46,18 @@ describes the default URL the submodule shall be cloned from.
 The logical name can be used for overriding this URL within your
 local repository configuration (see 'submodule init').
 
-This command will manage the tree entries and contents of the
-gitmodules file for you, as well as inspect the status of your
-submodules and update them.
-When adding a new submodule to the tree, the 'add' subcommand
-is to be used.  However, when pulling a tree containing submodules,
-these will not be checked out by default;
-the 'init' and 'update' subcommands will maintain submodules
-checked out and at appropriate revision in your working tree.
-You can briefly inspect the up-to-date status of your submodules
-using the 'status' subcommand and get a detailed overview of the
-difference between the index and checkouts using the 'summary'
-subcommand.
-
+Submodules are not to be confused with remotes, which are other
+repositories of the same project; submodules are meant for
+different projects you would like to make part of your source tree,
+while the history of the two projects still stays completely
+independent and you cannot modify the contents of the submodule
+from within the main project.
+If you want to merge the project histories and want to treat the
+aggregated whole as a single project from then on, you may want to
+add a remote for the other project and use the 'subtree' merge strategy,
+instead of treating the other project as a submodule. Directories
+that come from both projects can be cloned and checked out as a whole
+if you choose to go that route.
 
 COMMANDS
 --------
-- 
2.4.1.345.gab207b6.dirty

^ permalink raw reply related	[relevance 23%]

* [PATCH] glossary: add "remote" and "submodule"
@ 2015-05-27 21:13  9% Stefan Beller
  2015-05-27 22:29  7% ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-05-27 21:13 UTC (permalink / raw)
  To: gitster; +Cc: philipoakley, git, hvoigt, Stefan Beller

Noticed-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Documentation/glossary-content.txt | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index bf383c2..e303135 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -469,6 +469,11 @@ The most notable example is `HEAD`.
 	<<def_push,push>> to describe the mapping between remote
 	<<def_ref,ref>> and local ref.
 
+[[def_remote]]remote repository::
+	A <<def_repository,repository>> which is used to track the same
+	project but resides somewhere else. To communicate with remotes,
+	see <<def_fetch,fetch>> or <<def_push,push>>.
+
 [[def_remote_tracking_branch]]remote-tracking branch::
 	A <<def_ref,ref>> that is used to follow changes from another
 	<<def_repository,repository>>. It typically looks like
@@ -515,6 +520,11 @@ The most notable example is `HEAD`.
 	is created by giving the `--depth` option to linkgit:git-clone[1], and
 	its history can be later deepened with linkgit:git-fetch[1].
 
+[[def_submodule]]submodule::
+	A <<def_repository,repository>> inside another repository. The two
+	repositories have different history, though the outer repository
+	knows the commit of the inner repository.
+
 [[def_symref]]symref::
 	Symbolic reference: instead of containing the <<def_SHA1,SHA-1>>
 	id itself, it is of the format 'ref: refs/some/thing' and when
-- 
2.4.1.345.gab207b6.dirty

^ permalink raw reply related	[relevance 9%]

* Re: [PATCH] glossary: add "remote" and "submodule"
  2015-05-27 21:13  9% [PATCH] glossary: add "remote" and "submodule" Stefan Beller
@ 2015-05-27 22:29  7% ` Junio C Hamano
  2015-05-27 22:59  7%   ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-05-27 22:29 UTC (permalink / raw)
  To: Stefan Beller; +Cc: philipoakley, git, hvoigt

Stefan Beller <sbeller@google.com> writes:

> Noticed-by: Philip Oakley <philipoakley@iee.org>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>  Documentation/glossary-content.txt | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
> index bf383c2..e303135 100644
> --- a/Documentation/glossary-content.txt
> +++ b/Documentation/glossary-content.txt
> @@ -469,6 +469,11 @@ The most notable example is `HEAD`.
>  	<<def_push,push>> to describe the mapping between remote
>  	<<def_ref,ref>> and local ref.
>  
> +[[def_remote]]remote repository::
> +	A <<def_repository,repository>> which is used to track the same
> +	project but resides somewhere else. To communicate with remotes,
> +	see <<def_fetch,fetch>> or <<def_push,push>>.
> +

OK.

> @@ -515,6 +520,11 @@ The most notable example is `HEAD`.
>  	is created by giving the `--depth` option to linkgit:git-clone[1], and
>  	its history can be later deepened with linkgit:git-fetch[1].
>  
> +[[def_submodule]]submodule::
> +	A <<def_repository,repository>> inside another repository. The two
> +	repositories have different history, though the outer repository
> +	knows the commit of the inner repository.

I'd stress that they are not just different histories (as the
'master' and the 'maint' branches of my project has different
histories) but they are separate projects.  Perhaps like this?

       A repository that holds the history of a separate project
       inside another repository (the latter of which is called
       superproject).  The containing superproject knows about the
       names of (but does not hold copies of) commit objects of the
       contained submodules.

It is not like that it is strange or unintuitive that the
superproject knows about some commits in its submodule.  "X, though
Y" however makes it sound as if Y is true "despite X".  I do not
think there is any "despite" here.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] glossary: add "remote" and "submodule"
  2015-05-27 22:29  7% ` Junio C Hamano
@ 2015-05-27 22:59  7%   ` Stefan Beller
  2015-05-27 23:05  7%     ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-05-27 22:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Philip Oakley, git@vger.kernel.org, Heiko Voigt

On Wed, May 27, 2015 at 3:29 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> Noticed-by: Philip Oakley <philipoakley@iee.org>
>> Signed-off-by: Stefan Beller <sbeller@google.com>
>> ---
>>  Documentation/glossary-content.txt | 10 ++++++++++
>>  1 file changed, 10 insertions(+)
>>
>> diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
>> index bf383c2..e303135 100644
>> --- a/Documentation/glossary-content.txt
>> +++ b/Documentation/glossary-content.txt
>> @@ -469,6 +469,11 @@ The most notable example is `HEAD`.
>>       <<def_push,push>> to describe the mapping between remote
>>       <<def_ref,ref>> and local ref.
>>
>> +[[def_remote]]remote repository::
>> +     A <<def_repository,repository>> which is used to track the same
>> +     project but resides somewhere else. To communicate with remotes,
>> +     see <<def_fetch,fetch>> or <<def_push,push>>.
>> +
>
> OK.
>
>> @@ -515,6 +520,11 @@ The most notable example is `HEAD`.
>>       is created by giving the `--depth` option to linkgit:git-clone[1], and
>>       its history can be later deepened with linkgit:git-fetch[1].
>>
>> +[[def_submodule]]submodule::
>> +     A <<def_repository,repository>> inside another repository. The two
>> +     repositories have different history, though the outer repository
>> +     knows the commit of the inner repository.
>
> I'd stress that they are not just different histories (as the
> 'master' and the 'maint' branches of my project has different
> histories) but they are separate projects.  Perhaps like this?

This is a very subtle distinction IMHO, as both master and maint
"are the same project". Looking from enough distance, it's just the
git project without the fine detail of what makes these 2 histories different.
I tried coming up with a short paragraph, which may explain my choice
of words. But correctness trumps brevity indeed.

>
>        A repository that holds the history of a separate project
>        inside another repository (the latter of which is called
>        superproject).

This is better than what I proposed, but confusing. When naming
a project a submodule, my mental standpoint is the superproject.
("This project has the submodule foo and bar"). But In your description
the superproject is called "another repository".

>        The containing superproject knows about the
>        names of (but does not hold copies of) commit objects of the
>        contained submodules.

That makes sense to point out here. Though should we also introduce
"superproject" now?

>
> It is not like that it is strange or unintuitive that the
> superproject knows about some commits in its submodule.  "X, though
> Y" however makes it sound as if Y is true "despite X".  I do not
> think there is any "despite" here.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] glossary: add "remote" and "submodule"
  2015-05-27 22:59  7%   ` Stefan Beller
@ 2015-05-27 23:05  7%     ` Junio C Hamano
  2015-05-27 23:29  8%       ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-05-27 23:05 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Philip Oakley, git@vger.kernel.org, Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

>>> +[[def_submodule]]submodule::
>>> +     A <<def_repository,repository>> inside another repository. The two
>>> +     repositories have different history, though the outer repository
>>> +     knows the commit of the inner repository.
>>
> ... But correctness trumps brevity indeed.

I do not think the correct way is that much longer, though.

A repository inside another repository. The two repositories have different history
A repository that holds the history of a separate project inside another repository

Heh, they are the same length, no?

>
>>
>>        A repository that holds the history of a separate project
>>        inside another repository (the latter of which is called
>>        superproject).
>
> This is better than what I proposed, but confusing. When naming
> a project a submodule, my mental standpoint is the superproject.
> ("This project has the submodule foo and bar"). But In your description
> the superproject is called "another repository".

That is because you are adding an entry for "submodule" to the
glossary, no?  I was writing from submodule's point of view, i.e. "I
(submodule) is inside another repository, and my project is separate
from that other repository's".

>>        The containing superproject knows about the
>>        names of (but does not hold copies of) commit objects of the
>>        contained submodules.
>
> That makes sense to point out here. Though should we also introduce
> "superproject" now?

Yes, that is what I was hinting at.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] glossary: add "remote" and "submodule"
  2015-05-27 23:05  7%     ` Junio C Hamano
@ 2015-05-27 23:29  8%       ` Stefan Beller
  2015-05-28  1:50 10%         ` [PATCH] glossary: add "remote", "submodule", "superproject" Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-05-27 23:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Philip Oakley, git@vger.kernel.org, Heiko Voigt

On Wed, May 27, 2015 at 4:05 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>>>> +[[def_submodule]]submodule::
>>>> +     A <<def_repository,repository>> inside another repository. The two
>>>> +     repositories have different history, though the outer repository
>>>> +     knows the commit of the inner repository.
>>>
>> ... But correctness trumps brevity indeed.
>
> I do not think the correct way is that much longer, though.
>
> A repository inside another repository. The two repositories have different history
> A repository that holds the history of a separate project inside another repository
>
> Heh, they are the same length, no?
>
>>
>>>
>>>        A repository that holds the history of a separate project
>>>        inside another repository (the latter of which is called
>>>        superproject).
>>
>> This is better than what I proposed, but confusing. When naming
>> a project a submodule, my mental standpoint is the superproject.
>> ("This project has the submodule foo and bar"). But In your description
>> the superproject is called "another repository".
>
> That is because you are adding an entry for "submodule" to the
> glossary, no?  I was writing from submodule's point of view, i.e. "I
> (submodule) is inside another repository, and my project is separate
> from that other repository's".

The submodule doesn't know it's a submodule though, so the point of view
"I (as a submodule)" only happens rarely in the real world?
I have a library in mind when talking about submodules. And the libraries
maintainer may not care if their library is used as a submodule or just
"make install"ed or just put somewhere in the filesystem

Usually submodules are only interesting from the superprojects point of view,
like "I want to upgrade libfoo now, so I make a commit changing the gitlink
of the submodule to point at that tag/commit"
That's why I found the presented perspective a bit strange.

>
>>>        The containing superproject knows about the
>>>        names of (but does not hold copies of) commit objects of the
>>>        contained submodules.
>>
>> That makes sense to point out here. Though should we also introduce
>> "superproject" now?
>
> Yes, that is what I was hinting at.

ok

^ permalink raw reply	[relevance 8%]

* [PATCH] glossary: add "remote", "submodule", "superproject"
  2015-05-27 23:29  8%       ` Stefan Beller
@ 2015-05-28  1:50 10%         ` Stefan Beller
  2015-05-28 16:45  7%           ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-05-28  1:50 UTC (permalink / raw)
  To: git; +Cc: gitster, philipoakley, hvoigt, Stefan Beller

Noticed-by: Philip Oakley <philipoakley@iee.org>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Documentation/glossary-content.txt | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index bf383c2..23ab692 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -469,6 +469,11 @@ The most notable example is `HEAD`.
 	<<def_push,push>> to describe the mapping between remote
 	<<def_ref,ref>> and local ref.
 
+[[def_remote]]remote repository::
+	A <<def_repository,repository>> which is used to track the same
+	project but resides somewhere else. To communicate with remotes,
+	see <<def_fetch,fetch>> or <<def_push,push>>.
+
 [[def_remote_tracking_branch]]remote-tracking branch::
 	A <<def_ref,ref>> that is used to follow changes from another
 	<<def_repository,repository>>. It typically looks like
@@ -515,6 +520,18 @@ The most notable example is `HEAD`.
 	is created by giving the `--depth` option to linkgit:git-clone[1], and
 	its history can be later deepened with linkgit:git-fetch[1].
 
+[[def_submodule]]submodule::
+	A <<def_repository,repository>> that holds the history of a
+	separate project inside another repository (the latter of
+	which is called <<def_superproject, superproject>>). The
+	containing superproject knows about the names of (but does
+	not hold copies of) commit objects of the contained submodules.
+
+[[def_superproject]]superproject::
+	A <<def_repository,repository>> that references other repositories
+	inside itself as <<def_submodule,submodules>>. The superproject
+	tracks only the remote and the name of the submodule.
+
 [[def_symref]]symref::
 	Symbolic reference: instead of containing the <<def_SHA1,SHA-1>>
 	id itself, it is of the format 'ref: refs/some/thing' and when
-- 
2.4.1.345.gab207b6.dirty

^ permalink raw reply related	[relevance 10%]

* Re: [PATCH] glossary: add "remote", "submodule", "superproject"
  2015-05-28  1:50 10%         ` [PATCH] glossary: add "remote", "submodule", "superproject" Stefan Beller
@ 2015-05-28 16:45  7%           ` Junio C Hamano
  2015-05-28 17:52  7%             ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-05-28 16:45 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, philipoakley, hvoigt

Stefan Beller <sbeller@google.com> writes:

> Noticed-by: Philip Oakley <philipoakley@iee.org>
> Helped-by: Junio C Hamano <gitster@pobox.com>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>  Documentation/glossary-content.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)

The updates in this version relative to the previous one looks very
good, at least to me.  A bit more comments.

> diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
> index bf383c2..23ab692 100644
> --- a/Documentation/glossary-content.txt
> +++ b/Documentation/glossary-content.txt
> @@ -469,6 +469,11 @@ The most notable example is `HEAD`.
>  	<<def_push,push>> to describe the mapping between remote
>  	<<def_ref,ref>> and local ref.
>  
> +[[def_remote]]remote repository::
> +	A <<def_repository,repository>> which is used to track the same
> +	project but resides somewhere else. To communicate with remotes,
> +	see <<def_fetch,fetch>> or <<def_push,push>>.
> +

The last sentence sounds a tiny bit strange, in that I have to do a
bit more than just see the explanation of these commands in order to
communicate with remotes.

But it probably is just me.

> @@ -515,6 +520,18 @@ The most notable example is `HEAD`.
>  	is created by giving the `--depth` option to linkgit:git-clone[1], and
>  	its history can be later deepened with linkgit:git-fetch[1].
>  
> +[[def_submodule]]submodule::
> +	A <<def_repository,repository>> that holds the history of a
> +	separate project inside another repository (the latter of
> +	which is called <<def_superproject, superproject>>). The
> +	containing superproject knows about the names of (but does
> +	not hold copies of) commit objects of the contained submodules.

I agree with one point you mentioned in one of your messages, which
is that a submodule is not aware that it is used as part of a larger
project.  That makes me wonder if the last sentence sits better in
the description of the superproject, rather than the description of
the submodule.

> +[[def_superproject]]superproject::
> +	A <<def_repository,repository>> that references other repositories
> +	inside itself as <<def_submodule,submodules>>.

Perhaps "repositories of other projects"?  Does "inside" make it
clear enough that we are talking about the relationship between
working trees of the superproject and submodules?

> +	The superproject
> +	tracks only the remote and the name of the submodule.

I am not sure what this sentence means [*1*], and I do not know if
(a corrected version of) such a description is necessary here.

Thanks.

[Footnote]

*1* The superproject records a bit more than "remote and name" in
.gitmodules, and of course it records the history of the paths that
the submodule is bound to over time, with specific commits from the
submodule in its history.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] glossary: add "remote", "submodule", "superproject"
  2015-05-28 16:45  7%           ` Junio C Hamano
@ 2015-05-28 17:52  7%             ` Stefan Beller
  2015-05-28 18:50  4%               ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-05-28 17:52 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org, Philip Oakley, Heiko Voigt

On Thu, May 28, 2015 at 9:45 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> Noticed-by: Philip Oakley <philipoakley@iee.org>
>> Helped-by: Junio C Hamano <gitster@pobox.com>
>> Signed-off-by: Stefan Beller <sbeller@google.com>
>> ---
>>  Documentation/glossary-content.txt | 17 +++++++++++++++++
>>  1 file changed, 17 insertions(+)
>
> The updates in this version relative to the previous one looks very
> good, at least to me.  A bit more comments.
>
>> diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
>> index bf383c2..23ab692 100644
>> --- a/Documentation/glossary-content.txt
>> +++ b/Documentation/glossary-content.txt
>> @@ -469,6 +469,11 @@ The most notable example is `HEAD`.
>>       <<def_push,push>> to describe the mapping between remote
>>       <<def_ref,ref>> and local ref.
>>
>> +[[def_remote]]remote repository::
>> +     A <<def_repository,repository>> which is used to track the same
>> +     project but resides somewhere else. To communicate with remotes,
>> +     see <<def_fetch,fetch>> or <<def_push,push>>.
>> +
>
> The last sentence sounds a tiny bit strange, in that I have to do a
> bit more than just see the explanation of these commands in order to
> communicate with remotes.

Maybe s/see/use/ here?

>
> But it probably is just me.
>
>> @@ -515,6 +520,18 @@ The most notable example is `HEAD`.
>>       is created by giving the `--depth` option to linkgit:git-clone[1], and
>>       its history can be later deepened with linkgit:git-fetch[1].
>>
>> +[[def_submodule]]submodule::
>> +     A <<def_repository,repository>> that holds the history of a
>> +     separate project inside another repository (the latter of
>> +     which is called <<def_superproject, superproject>>). The
>> +     containing superproject knows about the names of (but does
>> +     not hold copies of) commit objects of the contained submodules.
>
> I agree with one point you mentioned in one of your messages, which
> is that a submodule is not aware that it is used as part of a larger
> project.  That makes me wonder if the last sentence sits better in
> the description of the superproject, rather than the description of
> the submodule.

Moved in the upcoming reroll.

>
>> +[[def_superproject]]superproject::
>> +     A <<def_repository,repository>> that references other repositories
>> +     inside itself as <<def_submodule,submodules>>.
>
> Perhaps "repositories of other projects"?  Does "inside" make it
> clear enough that we are talking about the relationship between
> working trees of the superproject and submodules?


    A <<def_repository,repository>> that references repositories
    of other projects in its working tree as <<def_submodule,submodules>>.

>
>> +     The superproject
>> +     tracks only the remote and the name of the submodule.
>
> I am not sure what this sentence means [*1*], and I do not know if
> (a corrected version of) such a description is necessary here.

When looking at submodules and subtrees I feel they behave similar
to symbolic and hard links. If you delete the remote of the submodule
you need to take care when dealing with the superproject, similar
to repairing a dangling symlink. ("Is it gone or just moved? Where
do I point it now?")

My intend here was to show that submodules are fragile like symlinks are.

Usually a repository (or a file in that analogy) is quite self contained,
if you have a copy of the repository, you can do lots of operation on it
like reading, changing(writing), moving. If there is a broken (git/sym-)link
reading in full becomes a hassle, as parts are missing.

I am not sure if the discussion belongs into the glossary though.
But where would you start looking for information if you want to decided
whether to use submodules or subtrees?

>
> Thanks.
>
> [Footnote]
>
> *1* The superproject records a bit more than "remote and name" in
> .gitmodules, and of course it records the history of the paths that
> the submodule is bound to over time, with specific commits from the
> submodule in its history.
>

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] glossary: add "remote", "submodule", "superproject"
  2015-05-28 17:52  7%             ` Stefan Beller
@ 2015-05-28 18:50  4%               ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-05-28 18:50 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git@vger.kernel.org, Philip Oakley, Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

> I am not sure if the discussion belongs into the glossary though.

Probably not.  Perhaps in tutorial.

^ permalink raw reply	[relevance 4%]

* [PATCH] glossary: add "remote", "submodule", "superproject"
@ 2015-05-29 18:23 12% Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-05-29 18:23 UTC (permalink / raw)
  To: gitster; +Cc: git, philipoakley, hvoigt, Stefan Beller

Noticed-by: Philip Oakley <philipoakley@iee.org>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
---

Moved information regarding the superproject from submodule to superproject,
and slightly reworded the superproject description.

 Documentation/glossary-content.txt | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index bf383c2..ab18f4b 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -469,6 +469,11 @@ The most notable example is `HEAD`.
 	<<def_push,push>> to describe the mapping between remote
 	<<def_ref,ref>> and local ref.
 
+[[def_remote]]remote repository::
+	A <<def_repository,repository>> which is used to track the same
+	project but resides somewhere else. To communicate with remotes,
+	see <<def_fetch,fetch>> or <<def_push,push>>.
+
 [[def_remote_tracking_branch]]remote-tracking branch::
 	A <<def_ref,ref>> that is used to follow changes from another
 	<<def_repository,repository>>. It typically looks like
@@ -515,6 +520,17 @@ The most notable example is `HEAD`.
 	is created by giving the `--depth` option to linkgit:git-clone[1], and
 	its history can be later deepened with linkgit:git-fetch[1].
 
+[[def_submodule]]submodule::
+	A <<def_repository,repository>> that holds the history of a
+	separate project inside another repository (the latter of
+	which is called <<def_superproject, superproject>>).
+
+[[def_superproject]]superproject::
+	A <<def_repository,repository>> that references repositories
+	of other projects in its working tree as <<def_submodule,submodules>>.
+	The superproject knows about the names of (but does not hold
+	copies of) commit objects of the contained submodules.
+
 [[def_symref]]symref::
 	Symbolic reference: instead of containing the <<def_SHA1,SHA-1>>
 	id itself, it is of the format 'ref: refs/some/thing' and when
-- 
2.4.1.345.gab207b6.dirty

^ permalink raw reply related	[relevance 12%]

* Re: [PATCH v2 08/19] pull: pass git-fetch's options to git-fetch
  @ 2015-06-03 17:16  2%   ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-06-03 17:16 UTC (permalink / raw)
  To: Paul Tan; +Cc: git@vger.kernel.org, Johannes Schindelin, Stephen Robin

On Tue, Jun 2, 2015 at 11:48 PM, Paul Tan <pyokagan@gmail.com> wrote:
> Since eb2a8d9 (pull: handle git-fetch's options as well, 2015-06-02),
> git-pull knows about and handles git-fetch's options, passing them to
> git-fetch. Re-implement this behavior.
>
> Since 29609e6 (pull: do nothing on --dry-run, 2010-05-25) git-pull
> supported the --dry-run option, exiting after git-fetch if --dry-run is
> set. Re-implement this behavior.
>
> Signed-off-by: Paul Tan <pyokagan@gmail.com>
> ---
>
> Notes:
>     v2
>
>     * Use parse_opt_parse_strbuf()
>
>  builtin/pull.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 95 insertions(+)
>
> diff --git a/builtin/pull.c b/builtin/pull.c
> index 5f08634..0b66b43 100644
> --- a/builtin/pull.c
> +++ b/builtin/pull.c
> @@ -32,6 +32,21 @@ static struct argv_array opt_strategies = ARGV_ARRAY_INIT;
>  static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT;
>  static struct strbuf opt_gpg_sign = STRBUF_INIT;
>
> +/* Options passed to git-fetch */
> +static struct strbuf opt_all = STRBUF_INIT;
> +static struct strbuf opt_append = STRBUF_INIT;
> +static struct strbuf opt_upload_pack = STRBUF_INIT;
> +static int opt_force;
> +static struct strbuf opt_tags = STRBUF_INIT;
> +static struct strbuf opt_prune = STRBUF_INIT;
> +static struct strbuf opt_recurse_submodules = STRBUF_INIT;
> +static int opt_dry_run;
> +static struct strbuf opt_keep = STRBUF_INIT;
> +static struct strbuf opt_depth = STRBUF_INIT;
> +static struct strbuf opt_unshallow = STRBUF_INIT;
> +static struct strbuf opt_update_shallow = STRBUF_INIT;
> +static struct strbuf opt_refmap = STRBUF_INIT;
> +
>  static struct option pull_options[] = {
>         /* Shared options */
>         OPT__VERBOSITY(&opt_verbosity),
> @@ -82,6 +97,46 @@ static struct option pull_options[] = {
>           N_("GPG sign commit"),
>           PARSE_OPT_OPTARG, parse_opt_pass_strbuf },
>
> +       /* Options passed to git-fetch */
> +       OPT_GROUP(N_("Options related to fetching")),
> +       { OPTION_CALLBACK, 0, "all", &opt_all, 0,
> +         N_("fetch from all remotes"),
> +         PARSE_OPT_NOARG, parse_opt_pass_strbuf },
> +       { OPTION_CALLBACK, 'a', "append", &opt_append, 0,
> +         N_("append to .git/FETCH_HEAD instead of overwriting"),
> +         PARSE_OPT_NOARG, parse_opt_pass_strbuf },
> +       { OPTION_CALLBACK, 0, "upload-pack", &opt_upload_pack, N_("path"),
> +         N_("path to upload pack on remote end"),
> +         0, parse_opt_pass_strbuf },
> +       OPT__FORCE(&opt_force, N_("force overwrite of local branch")),
> +       { OPTION_CALLBACK, 't', "tags", &opt_tags, 0,
> +         N_("fetch all tags and associated objects"),
> +         PARSE_OPT_NOARG, parse_opt_pass_strbuf },
> +       { OPTION_CALLBACK, 'p', "prune", &opt_prune, 0,
> +         N_("prune remote-tracking branches no longer on remote"),
> +         PARSE_OPT_NOARG, parse_opt_pass_strbuf },
> +       { OPTION_CALLBACK, 0, "recurse-submodules", &opt_recurse_submodules,
> +         N_("on-demand"),
> +         N_("control recursive fetching of submodules"),
> +         PARSE_OPT_OPTARG, parse_opt_pass_strbuf },
> +       OPT_BOOL(0, "dry-run", &opt_dry_run,
> +               N_("dry run")),
> +       { OPTION_CALLBACK, 'k', "keep", &opt_keep, 0,
> +         N_("keep downloaded pack"),
> +         PARSE_OPT_NOARG, parse_opt_pass_strbuf },
> +       { OPTION_CALLBACK, 0, "depth", &opt_depth, N_("depth"),
> +         N_("deepen history of shallow clone"),
> +         0, parse_opt_pass_strbuf },
> +       { OPTION_CALLBACK, 0, "unshallow", &opt_unshallow, 0,
> +         N_("convert to a complete repository"),
> +         PARSE_OPT_NONEG | PARSE_OPT_NOARG, parse_opt_pass_strbuf },
> +       { OPTION_CALLBACK, 0, "update-shallow", &opt_update_shallow, 0,
> +         N_("accept refs that update .git/shallow"),
> +         PARSE_OPT_NOARG, parse_opt_pass_strbuf },
> +       { OPTION_CALLBACK, 0, "refmap", &opt_refmap, N_("refmap"),
> +         N_("specify fetch refmap"),
> +         PARSE_OPT_NONEG, parse_opt_pass_strbuf },
> +
>         OPT_END()
>  };
>
> @@ -100,6 +155,16 @@ static void argv_push_verbosity(struct argv_array *arr)
>  }
>
>  /**
> + * Pushes "-f" switches into arr to match the opt_force level.
> + */
> +static void argv_push_force(struct argv_array *arr)
> +{
> +       int force = opt_force;
> +       while (force-- > 0)

This made me chuckle despite the formatting,
as we referred to it as the limes operator in school for fun

    #define limes while
    limes (n --> 0) { // n goes towards zero
        ...
    }

A quick
    grep -r "--" -- *.c |grep while
shows we actually use this quite a lot, though the "> 0" is
omitted quite often.

> +               argv_array_push(arr, "-f");
> +}
> +
> +/**
>   * Parses argv into [<repo> [<refspecs>...]], returning their values in `repo`
>   * as a string and `refspecs` as a null-terminated array of strings. If `repo`
>   * is not provided in argv, it is set to NULL.
> @@ -131,6 +196,33 @@ static int run_fetch(const char *repo, const char **refspecs)
>         if (opt_progress.len)
>                 argv_array_push(&args, opt_progress.buf);
>
> +       /* Options passed to git-fetch */
> +       if (opt_all.len)
> +               argv_array_push(&args, opt_all.buf);
> +       if (opt_append.len)
> +               argv_array_push(&args, opt_append.buf);
> +       if (opt_upload_pack.len)
> +               argv_array_push(&args, opt_upload_pack.buf);
> +       argv_push_force(&args);
> +       if (opt_tags.len)
> +               argv_array_push(&args, opt_tags.buf);
> +       if (opt_prune.len)
> +               argv_array_push(&args, opt_prune.buf);
> +       if (opt_recurse_submodules.len)
> +               argv_array_push(&args, opt_recurse_submodules.buf);
> +       if (opt_dry_run)
> +               argv_array_push(&args, "--dry-run");
> +       if (opt_keep.len)
> +               argv_array_push(&args, opt_keep.buf);
> +       if (opt_depth.len)
> +               argv_array_push(&args, opt_depth.buf);
> +       if (opt_unshallow.len)
> +               argv_array_push(&args, opt_unshallow.buf);
> +       if (opt_update_shallow.len)
> +               argv_array_push(&args, opt_update_shallow.buf);
> +       if (opt_refmap.len)
> +               argv_array_push(&args, opt_refmap.buf);
> +
>         if (repo)
>                 argv_array_push(&args, repo);
>         while (*refspecs)
> @@ -199,5 +291,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
>         if (run_fetch(repo, refspecs))
>                 return 1;
>
> +       if (opt_dry_run)
> +               return 0;
> +
>         return run_merge();
>  }
> --
> 2.1.4
>

^ permalink raw reply	[relevance 2%]

* Re: Submodules as first class citizens (was Re: Moving to subtrees for plugins?)
  @ 2015-06-07  6:26  4%   ` Stefan Beller
  2015-06-09 18:40  7%     ` Jens Lehmann
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-06-07  6:26 UTC (permalink / raw)
  To: Luca Milanesio, Phil Hord; +Cc: Repo Discussion, Git, Heiko Voigt, Jens Lehmann

On 06.06.2015 12:53, Luca Milanesio wrote:
> Thank you Phil, you anticipated me :-)
> 
> Luca.
> 
>> On 6 Jun 2015, at 18:49, Phil Hord <phil.hord@gmail.com> wrote:
>>
>> On Fri, Jun 5, 2015, 2:58 AM lucamilanesio <luca.milanesio@gmail.com> wrote:
>>>>
>>>> Some devs of my Team complained that with submodules it is
>>>> difficult to see the “full picture” of the difference
>>>> between two SHA1 on the root project, as the submodules
>>>> would just show as different SHA1s. When you Google
>>>> “subtree submodules” you find other opinions as well:
>>>>
>>>> Just to mention a few:
>>>> -
>>>> https://codingkilledthecat.wordpress.com/2012/04/28/why-y
>>>> our-company-shouldnt-use-git-submodules/ -
>>>> http://blogs.atlassian.com/2013/05/alternatives-to-git-su
>>>> bmodule-git-subtree/
>>>>
>>>> To be honest with you, I am absolutely fine with
>>>> submodules as I can easily leave with the “extra pain” of
>>>> diffing by hand recursively on submodules. But it is true
>>>> that it may happen to either forget to do a git submodule
>>>> update or otherwise forget you are in a detached branch
>>>> and start committing “on the air” without a branch.
>>
>> ...
>>
>>> Ideally, as a "git clone --recursive" already exists, I would like to
>>> see a "git diff --recursive" that goes through the submodules as well :-)
>>>
>>> Something possibly to propose to the Git mailing list?
>>
>>
>> I've worked on git diff --recursive a bit myself, along with some
>> simpler use cases (git ls-tree --recursive) as POCs. I think some of
>> the needs there begin to have ui implications which could be
>> high-friction. I really want to finish it someday, but I've been too
>> busy lately at $job, and now my experiments are all rather stale.
>>
>> It would be a good discussion to have over at the git list (copied).
>> Heiko and Jens have laid some new groundwork in this area and it may
>> be a good time to revisit it.  Or maybe they've even moved deeper than
>> that; I have been distracted for well over a year now.
>>

Glad you're working (or planning to) working on submodulues. This is
also on my todo list for the next months as well.

I'd review stuff in that area if you're looking for reviewers.

Stefan

>> Phil
> 
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[relevance 4%]

* Re: Submodules as first class citizens (was Re: Moving to subtrees for plugins?)
  2015-06-07  6:26  4%   ` Stefan Beller
@ 2015-06-09 18:40  7%     ` Jens Lehmann
  2015-06-11 16:11  4%       ` Phil Hord
  2015-06-15  9:03  2%       ` Heiko Voigt
  0 siblings, 2 replies; 200+ results
From: Jens Lehmann @ 2015-06-09 18:40 UTC (permalink / raw)
  To: Stefan Beller, Luca Milanesio, Phil Hord
  Cc: Repo Discussion, Git, Heiko Voigt

Am 07.06.2015 um 08:26 schrieb Stefan Beller:
> On 06.06.2015 12:53, Luca Milanesio wrote:
>>> On 6 Jun 2015, at 18:49, Phil Hord <phil.hord@gmail.com> wrote:
>>> On Fri, Jun 5, 2015, 2:58 AM lucamilanesio <luca.milanesio@gmail.com> wrote:
>>>> Ideally, as a "git clone --recursive" already exists, I would like to
>>>> see a "git diff --recursive" that goes through the submodules as well :-)
>>>>
>>>> Something possibly to propose to the Git mailing list?

Such an option makes lots of sense to me (though "--recurse-submodules"
should be its name for consistency reasons). This could be an alias for
"--submodule=full", as the "--submodule" option controls the format of
submodule diffs.

>>> I've worked on git diff --recursive a bit myself, along with some
>>> simpler use cases (git ls-tree --recursive) as POCs. I think some of
>>> the needs there begin to have ui implications which could be
>>> high-friction. I really want to finish it someday, but I've been too
>>> busy lately at $job, and now my experiments are all rather stale.
>>>
>>> It would be a good discussion to have over at the git list (copied).
>>> Heiko and Jens have laid some new groundwork in this area and it may
>>> be a good time to revisit it.  Or maybe they've even moved deeper than
>>> that; I have been distracted for well over a year now.
>>>
>
> Glad you're working (or planning to) working on submodulues. This is
> also on my todo list for the next months as well.

More hands are always welcome!

> I'd review stuff in that area if you're looking for reviewers.

I'll be happy help too.

^ permalink raw reply	[relevance 7%]

* Re: Submodules as first class citizens (was Re: Moving to subtrees for plugins?)
  2015-06-09 18:40  7%     ` Jens Lehmann
@ 2015-06-11 16:11  4%       ` Phil Hord
  2015-06-11 18:56  5%         ` Jens Lehmann
  2015-06-15  9:03  2%       ` Heiko Voigt
  1 sibling, 1 reply; 200+ results
From: Phil Hord @ 2015-06-11 16:11 UTC (permalink / raw)
  To: Jens Lehmann
  Cc: Stefan Beller, Luca Milanesio, Repo Discussion, Git, Heiko Voigt,
	Phil Hord

On Tue, Jun 9, 2015 at 2:40 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
> Am 07.06.2015 um 08:26 schrieb Stefan Beller:
>>
>> On 06.06.2015 12:53, Luca Milanesio wrote:
>>>>
>>>> On 6 Jun 2015, at 18:49, Phil Hord <phil.hord@gmail.com> wrote:
>>>> On Fri, Jun 5, 2015, 2:58 AM lucamilanesio <luca.milanesio@gmail.com>
>>>> wrote:
>>>>>
>>>>> Ideally, as a "git clone --recursive" already exists, I would like to
>>>>> see a "git diff --recursive" that goes through the submodules as well
>>>>> :-)
>>>>>
>>>>> Something possibly to propose to the Git mailing list?
>
>
> Such an option makes lots of sense to me (though "--recurse-submodules"
> should be its name for consistency reasons). This could be an alias for
> "--submodule=full", as the "--submodule" option controls the format of
> submodule diffs.

To me, --recurse-submodules means submodules are still not first-class
citizens.  But let's put that aside for a moment; I don't care about
the switch name too much as long as I can configure
'diff.recurse-submodules = true'.

[The following is rather long.  I'm sorry for that.  Feel free to look
away when it gets too vague.]

Let me set up a submodule like so:

  $ git init /tmp/Super && cd /tmp/Super
  Super$ git submodule add https://github.com/gitster/git.git Foo

I wish to be able to grep from Super and find matches in all my submodules.

  Super$ git grep --recurse-submodules base--int
  Foo/.gitignore:/git-rebase--interactive
  Foo/Makefile:SCRIPT_LIB += git-rebase--interactive

But I want this to work naturally across git-module boundaries, so I
want this also to work (grepping a super-project from within a
submodule):

  Super$ cd Foo
  Foo$ git grep --recurse-submodules base--int ..
  .gitignore:/git-rebase--interactive
  Makefile:SCRIPT_LIB += git-rebase--interactive

I expect some groans from the audience here, because I think if the
syntax above worked, then so would this:

  $ cd /tmp
  tmp$ git grep base--int /tmp/Super/Foo
  /tmp/Super/Foo/.gitignore:/git-rebase--interactive
  /tmp/Super/Foo/Makefile:SCRIPT_LIB += git-rebase--interactive

This usage has nothing to do with submodules, really, except that it
allows git commands to reach into foreign git directories by virtue of
the path supplied as some argument instead of via $GITDIR, and in
doing so it helps solve some git submodules use cases of mine.

But if that did not turn your stomach, try this one:

  $ cd /tmp/Super
  Super$ printf "Some submodule data">Foo/data.txt
  Super$ git add Foo/data.txt
  fatal: Pathspec 'Foo/data.txt' is in submodule 'Foo'
  Super$ git add --recurse-submodules Foo/data.txt

Some notes on this usage:

1. --recurse-submodules seems like a reasonable name for this switch,
especially when you consider the 'git add --recurse-submodules .' use
case.

2. This recursive 'git add' seems dangerous to me unless git-status
also shows all the changed/untracked files in submodules as well if
the --recurse-submodules switch is included.  This would support the
expectation that 'git add .' is going to add the files shown by 'git
status .'

3. Configuring --recurse-submodules as the default mode for 'git add'
but not for 'git status' seems reckless enough that I think there
should not be separate options for these two commands.  There are
probably many other "cross-command" scenarios with similar coupling.

Moving on, as we have :/ to mean 'workdir root', I wonder how you
would spell "super-project workdir root".  Maybe it would be ::/

I realize the kinds of features I'm talking about require extensive
code changes in Git.  For example, consider the meaning of this:

  Super$ git diff --recurse-submodules origin/next origin/master

Since I created Super just a few minutes ago and it has no remote
named 'origin', this command seems meaningless to me.  But suppose
that origin/next and origin/master did exist in my Super project.
Then, I would expect in my wishlist Git, that

A.  Super$ git diff --recurse-submodules origin/next origin/master
This would include differences in Foo between origin/master:Foo and
origin/next:Foo; that is, the commits referenced from those gitlinks
in Super.

B.  Super$ git diff --recurse-submodules origin/next HEAD
This would include differences in Foo between origin/master:Foo and
HEAD:Foo; that is, the commits referenced from those gitlinks in
Super.

C.  Super$ git diff --recurse-submodules origin/next
This would include differences in Foo between origin/master:Foo and
the current Foo workdir.

D.  Super$ cd Foo && git diff origin/next
This would include differences in Foo between the Foo submodule's
origin/master and the current Foo workdir.

Now, C and D seem confusingly similar to me and technically very
different.  I could understand the results, but I could easily be led
astray, especially if I am writing a script.  But I still think it is
reasonable and correct.

I think this could have dire consequences for some commands like 'git
apply'. But I think it is reasonable for git apply to reject such
cross-project diffs, at least in the beginning.  :-)

While I am thinking about it, let me also mention these cases:
E.  Super$ git diff --recurse-submodules origin/next origin/master -- Foo
I think 'origin/next' and 'origin/master' here are referring to
Super's refs, but I can imagine an implementer choosing to use Foo's
instead.

F.  Super$ cd Foo
      Foo$ git diff --recurse-submodules origin/next origin/master -- ..
If this worked, I would think 'origin/next' and 'origin/master' here
must refer to Super's refs even though I began in Foo.  This one is so
ambiguous I think I would have to call this an error.  More
specifically, I think it would have to be rewritten like this next one
(G).

G.  Super$ cd Foo
      Foo$ git -C .. diff --recurse-submodules origin/next origin/master
That is, at least for 'git diff', the <path> parameter at the end is
only used to filter the results; it is not used to find the git-dir.

But look at me speaking in the present tense.  How silly.  I live too
much in my own imagination.

Phil

-- 

^ permalink raw reply	[relevance 4%]

* Re: Submodules as first class citizens (was Re: Moving to subtrees for plugins?)
  2015-06-11 16:11  4%       ` Phil Hord
@ 2015-06-11 18:56  5%         ` Jens Lehmann
  0 siblings, 0 replies; 200+ results
From: Jens Lehmann @ 2015-06-11 18:56 UTC (permalink / raw)
  To: Phil Hord
  Cc: Stefan Beller, Luca Milanesio, Repo Discussion, Git, Heiko Voigt,
	Phil Hord

Am 11.06.2015 um 18:11 schrieb Phil Hord:
> On Tue, Jun 9, 2015 at 2:40 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
>> Am 07.06.2015 um 08:26 schrieb Stefan Beller:
>>>
>>> On 06.06.2015 12:53, Luca Milanesio wrote:
>>>>>
>>>>> On 6 Jun 2015, at 18:49, Phil Hord <phil.hord@gmail.com> wrote:
>>>>> On Fri, Jun 5, 2015, 2:58 AM lucamilanesio <luca.milanesio@gmail.com>
>>>>> wrote:
>>>>>>
>>>>>> Ideally, as a "git clone --recursive" already exists, I would like to
>>>>>> see a "git diff --recursive" that goes through the submodules as well
>>>>>> :-)
>>>>>>
>>>>>> Something possibly to propose to the Git mailing list?
>>
>>
>> Such an option makes lots of sense to me (though "--recurse-submodules"
>> should be its name for consistency reasons). This could be an alias for
>> "--submodule=full", as the "--submodule" option controls the format of
>> submodule diffs.
>
> To me, --recurse-submodules means submodules are still not first-class
> citizens.  But let's put that aside for a moment; I don't care about
> the switch name too much as long as I can configure
> 'diff.recurse-submodules = true'.

After somebody implemented the 'full' mode for 'diff --submodule',
setting 'diff.submodule' to 'full' would make --recurse-submodules the
default for diff (unless recursing into the submodules is overridden
by either the global 'diff.ignoreSubmodules' or the per-submodule
'submodule.<name>.ignore' setting of course).

> [The following is rather long.  I'm sorry for that.  Feel free to look
> away when it gets too vague.]

Sorry, that was too long for todays git time budget ;-)

^ permalink raw reply	[relevance 5%]

* Re: Submodules as first class citizens (was Re: Moving to subtrees for plugins?)
  2015-06-09 18:40  7%     ` Jens Lehmann
  2015-06-11 16:11  4%       ` Phil Hord
@ 2015-06-15  9:03  2%       ` Heiko Voigt
  1 sibling, 0 replies; 200+ results
From: Heiko Voigt @ 2015-06-15  9:03 UTC (permalink / raw)
  To: Jens Lehmann
  Cc: Stefan Beller, Luca Milanesio, Phil Hord, Repo Discussion, Git

On Tue, Jun 09, 2015 at 08:40:14PM +0200, Jens Lehmann wrote:
> Am 07.06.2015 um 08:26 schrieb Stefan Beller:
> >On 06.06.2015 12:53, Luca Milanesio wrote:
> >>>On 6 Jun 2015, at 18:49, Phil Hord <phil.hord@gmail.com> wrote:
> >>>On Fri, Jun 5, 2015, 2:58 AM lucamilanesio <luca.milanesio@gmail.com> wrote:
> >>>>Ideally, as a "git clone --recursive" already exists, I would like to
> >>>>see a "git diff --recursive" that goes through the submodules as well :-)
> >>>>
> >>>>Something possibly to propose to the Git mailing list?
> 
> Such an option makes lots of sense to me (though "--recurse-submodules"
> should be its name for consistency reasons). This could be an alias for
> "--submodule=full", as the "--submodule" option controls the format of
> submodule diffs.

BTW, for long running topics (or low hanging fruits) we collect/link
everything in the wiki of Jens git fork on github. This is the central
page:

https://github.com/jlehmann/git-submod-enhancements/wiki

Maybe everyone that has work in the queue can add his work there (the work that
takes more time) so we can avoid doubling any effort. Not everything there is
up to date at the moment but I will look into it to remove outdated things.

> >>>I've worked on git diff --recursive a bit myself, along with some
> >>>simpler use cases (git ls-tree --recursive) as POCs. I think some of
> >>>the needs there begin to have ui implications which could be
> >>>high-friction. I really want to finish it someday, but I've been too
> >>>busy lately at $job, and now my experiments are all rather stale.
> >>>
> >>>It would be a good discussion to have over at the git list (copied).
> >>>Heiko and Jens have laid some new groundwork in this area and it may
> >>>be a good time to revisit it.  Or maybe they've even moved deeper than
> >>>that; I have been distracted for well over a year now.
> >>>
> >
> >Glad you're working (or planning to) working on submodulues. This is
> >also on my todo list for the next months as well.
> 
> More hands are always welcome!
> 
> >I'd review stuff in that area if you're looking for reviewers.
> 
> I'll be happy help too.

Me too.

Cheers Heiko

^ permalink raw reply	[relevance 2%]

* [ANNOUNCE] Git v2.4.4
@ 2015-06-16 22:15  4% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-06-16 22:15 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

The latest maintenance release Git v2.4.4 is now available at
the usual places.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/

The following public repositories all have a copy of the 'v2.4.4'
tag and the 'maint' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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 v2.4.4 Release Notes
========================

Fixes since v2.4.3
------------------

 * l10n updates for German.

 * An earlier leakfix to bitmap testing code was incomplete.

 * "git clean pathspec..." tried to lstat(2) and complain even for
   paths outside the given pathspec.

 * Communication between the HTTP server and http_backend process can
   lead to a dead-lock when relaying a large ref negotiation request.
   Diagnose the situation better, and mitigate it by reading such a
   request first into core (to a reasonable limit).

 * The clean/smudge interface did not work well when filtering an
   empty contents (failed and then passed the empty input through).
   It can be argued that a filter that produces anything but empty for
   an empty input is nonsense, but if the user wants to do strange
   things, then why not?

 * Make "git stash something --help" error out, so that users can
   safely say "git stash drop --help".

 * Clarify that "log --raw" and "log --format=raw" are unrelated
   concepts.

 * Catch a programmer mistake to feed a pointer not an array to
   ARRAY_SIZE() macro, by using a couple of GCC extensions.

Also contains typofixes, documentation updates and trivial code
clean-ups.

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

Changes since v2.4.3 are as follows:

Alex Henrie (1):
      blame, log: format usage strings similarly to those in documentation

David Turner (1):
      clean: only lstat files in pathspec

Elia Pinto (1):
      git-compat-util.h: implement a different ARRAY_SIZE macro for for safely deriving the size of array

Jeff King (8):
      http-backend: fix die recursion with custom handler
      t5551: factor out tag creation
      stash: complain about unknown flags
      stash: recognize "--help" for subcommands
      test_bitmap_walk: free bitmap with bitmap_free
      http-backend: spool ref negotiation requests to buffer
      clone: use OPT_STRING_LIST for --reference
      clone: reorder --dissociate and --reference options

Jim Hill (1):
      sha1_file: pass empty buffer to index empty file

Junio C Hamano (1):
      Git 2.4.4

Matthieu Moy (2):
      Documentation/log: clarify what --raw means
      Documentation/log: clarify sha1 non-abbreviation in log --raw

Michael Coleman (1):
      Documentation/git-commit: grammofix

Michael J Gruber (3):
      l10n: de.po: grammar fix
      l10n: de.po: punctuation fixes
      l10n: de.po: translation fix for fall-back to 3way merge

Phillip Sz (1):
      l10n: de.po: change error message from "sagen" to "Meinten Sie"

René Scharfe (3):
      use file_exists() to check if a file exists in the worktree
      clean: remove unused variable buf
      dir: remove unused variable sb

Stefan Beller (2):
      submodule doc: reorder introductory paragraphs
      glossary: add "remote", "submodule", "superproject"

^ permalink raw reply	[relevance 4%]

* Re: RFC/Pull Request: Refs db backend
  @ 2015-06-23 17:16  2% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-06-23 17:16 UTC (permalink / raw)
  To: David Turner; +Cc: git mailing list, ronnie sahlberg

[+<ronniesahlberg@gmail.com>, FYI]

On Mon, Jun 22, 2015 at 5:50 PM, David Turner <dturner@twopensource.com> wrote:
> I've revived and modified Ronnie Sahlberg's work on the refs db
> backend.

Awesome!

>
> The work is on top of be3c13e5564, Junio's "First batch for 2.5 cycle".
> I recognize that there have been changes to the refs code since then,
> and that there are some further changes in-flight from e.g. Michael
> Haggerty.  If there is interest in this, I can rebase once Michael's
> changes land.

Originally I wanted to continue on Ronnies work, but because of the churn
in refs I stopped it for a while and took care of other projects (and wanted
to come back eventually). Thanks for reviving this topic!

> The changes can be found here:
> https://github.com/dturner-tw/git.git on the dturner/pluggable-backends
> branch
>
> The db backend code was added in the penultimate commit; the rest is
> just code rearrangement and minor changes to make alternate backends
> possible.  There ended up being a fair amount of this rearrangement, but
> the end result is that almost the entire git test suite runs under the
> db backend without error (see below for details).

Looking at the end result in refs-be-db.c it feels like there are more
functions in the refs_be_db struct, did this originate from other design
choices? IIRC Ronnie wanted to have as least functions in there as
possible, and share as much of the code between the databases, such
that the glue between the db and the refs code is minimal.

Some random comments from looking over the branch briefly:

In the latest commit, (refs: tests for db backend), I am unsure about the
copyright annotations. At least a sole "Copyright (c) 2007 Junio C Hamano"
doesn't make sense to me. ;)

Typo in commit message "bisect: use refs insfrastructure for BISECT_START"

Some commits contain a ChangeId, which is a Gerrit leftover. :(

Thanks,
Stefan

>
> The db backend runs git for-each-ref about 30% faster than the files
> backend with fully-packed refs on a repo with ~120k refs.  It's also
> about 4x faster than using fully-unpacked refs.  In addition, and
> perhaps more importantly, it avoids case-conflict issues on OS X.
>
> I chose to use LMDB for the database.  LMDB has a few features that make
> it suitable for usage in git:
>
> 1. It is relatively lightweight; it requires only one header file, and
> the library itself is under 300k (as opposed to 700k for
> e.g. sqlite).
>
> 2. It is well-tested: it's been used in OpenLDAP for years.
>
> 3. It's very fast.  LMDB's benchmarks show that it is among
> the fastest key-value stores.
>
> 4. It has a relatively simple concurrency story; readers don't
> block writers and writers don't block readers.
>
> Ronnie Sahlberg's original version of this patchset used tdb.  The
> advantage of tdb is that it's smaller (~125k).  The disadvantages are
> that tdb is hard to build on OS X.  It's also not in homebrew.  So lmdb
> seemed simpler.
>
> To test this backend's correctness, I hacked test-lib.sh and
> test-lib-functions.sh to run all tests under the refs backend. Dozens
> of tests use manual ref/reflog reading/writing, or create submodules
> without passing --refs-backend-type to git init.  If those tests are
> changed to use the update-ref machinery or test-refs-be-db (or, in the
> case of packed-refs, corrupt refs, and dumb fetch tests, are skipped),
> the only remaining failing tests are the git-new-workdir tests and the
> gitweb tests.
>
> Please let me know how it would be best to proceed.
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in

^ permalink raw reply	[relevance 2%]

* Re: Dependency Management
  @ 2015-06-23 17:34  4%   ` Stefan Beller
  2015-06-23 18:49  4%     ` Josh Hagins
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-06-23 17:34 UTC (permalink / raw)
  To: Jean Audibert; +Cc: git@vger.kernel.org

On Tue, Jun 23, 2015 at 1:52 AM, Jean Audibert <jaudibert@euronext.com> wrote:
> Hi,
>
> Sorry to bother you with this question but I can't find any "official" answer or "strong opinion" from Git community.
>
> In my company we recently started to use Git and we wonder how to share code and manage dependencies with Git?
> Use case: in project P we need to include lib-a and lib-b (libraries shared by several projects)
>
> In your opinion, what is the "future proof" solution?
> * Use submodule
> * Use subtree
>
> We know there is lot of PRO/CONS but I feel that subtree is "behind" in the race and the latest version of submodule work fine

Use whatever works fine for your use case.

My personal opinion/expectation is to see submodules
improving/advancing more than subtrees advancing in the near future.
Though this is neither the official nor a strong opinion.

Stefan

>
> Suggestions are very welcome.
> Thanks in advance,
>
> Jean Audibert
>
>
> _________________________________________________________________
>
> This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of Euronext N.V. or any of its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 4%]

* Re: Dependency Management
  2015-06-23 17:34  4%   ` Stefan Beller
@ 2015-06-23 18:49  4%     ` Josh Hagins
  2015-06-25  9:00  0%       ` Luke Diamand
  0 siblings, 1 reply; 200+ results
From: Josh Hagins @ 2015-06-23 18:49 UTC (permalink / raw)
  To: Stefan Beller, Jean Audibert; +Cc: git@vger.kernel.org

If neither git-submodule nor git-subtree is palatable to you, here are
a couple of alternatives you might try:

  * https://github.com/ingydotnet/git-subrepo
  * https://github.com/tdd/git-stree

On Tue, Jun 23, 2015 at 1:36 PM Stefan Beller <sbeller@google.com> wrote:
>
> On Tue, Jun 23, 2015 at 1:52 AM, Jean Audibert <jaudibert@euronext.com> wrote:
> > Hi,
> >
> > Sorry to bother you with this question but I can't find any "official" answer or "strong opinion" from Git community.
> >
> > In my company we recently started to use Git and we wonder how to share code and manage dependencies with Git?
> > Use case: in project P we need to include lib-a and lib-b (libraries shared by several projects)
> >
> > In your opinion, what is the "future proof" solution?
> > * Use submodule
> > * Use subtree
> >
> > We know there is lot of PRO/CONS but I feel that subtree is "behind" in the race and the latest version of submodule work fine
>
> Use whatever works fine for your use case.
>
> My personal opinion/expectation is to see submodules
> improving/advancing more than subtrees advancing in the near future.
> Though this is neither the official nor a strong opinion.
>
> Stefan
>
> >
> > Suggestions are very welcome.
> > Thanks in advance,
> >
> > Jean Audibert
> >
> >
> > _________________________________________________________________
> >
> > This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of Euronext N.V. or any of its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe git" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 4%]

* Re: Dependency Management
  2015-06-23 18:49  4%     ` Josh Hagins
@ 2015-06-25  9:00  0%       ` Luke Diamand
  0 siblings, 0 replies; 200+ results
From: Luke Diamand @ 2015-06-25  9:00 UTC (permalink / raw)
  To: Josh Hagins, Stefan Beller, Jean Audibert; +Cc: git@vger.kernel.org

On 23/06/15 19:49, Josh Hagins wrote:
> If neither git-submodule nor git-subtree is palatable to you, here are
> a couple of alternatives you might try:
>
>    * https://github.com/ingydotnet/git-subrepo
>    * https://github.com/tdd/git-stree

You could also use Android's "repo" tool:

https://code.google.com/p/git-repo/

Luke

>
> On Tue, Jun 23, 2015 at 1:36 PM Stefan Beller <sbeller@google.com> wrote:
>>
>> On Tue, Jun 23, 2015 at 1:52 AM, Jean Audibert <jaudibert@euronext.com> wrote:
>>> Hi,
>>>
>>> Sorry to bother you with this question but I can't find any "official" answer or "strong opinion" from Git community.
>>>
>>> In my company we recently started to use Git and we wonder how to share code and manage dependencies with Git?
>>> Use case: in project P we need to include lib-a and lib-b (libraries shared by several projects)
>>>
>>> In your opinion, what is the "future proof" solution?
>>> * Use submodule
>>> * Use subtree
>>>
>>> We know there is lot of PRO/CONS but I feel that subtree is "behind" in the race and the latest version of submodule work fine
>>
>> Use whatever works fine for your use case.
>>
>> My personal opinion/expectation is to see submodules
>> improving/advancing more than subtrees advancing in the near future.
>> Though this is neither the official nor a strong opinion.
>>
>> Stefan
>>
>>>
>>> Suggestions are very welcome.
>>> Thanks in advance,
>>>
>>> Jean Audibert
>>>

^ permalink raw reply	[relevance 0%]

* [ANNOUNCE] Git v2.5.0-rc0
@ 2015-06-25 20:19  1% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-06-25 20:19 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

An early preview release Git v2.5.0-rc0 is now available for
testing at the usual places.  It is comprised of 492 non-merge
commits since v2.4.0, contributed by 54 people, 17 of which are
new faces.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/testing/

The following public repositories all have a copy of the
'v2.5.0-rc0' tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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

New contributors whose contributions weren't in v2.4.0 are as follows.
Welcome to the Git development community!

  Allen Hubbe, Ariel Faigon, Blair Holloway, Christian Neukirchen,
  Danny Lin, Frans Klaver, Fredrik Medley, Lars Kellogg-Stedman,
  Lex Spoon, Luke Mewburn, Miguel Torroja, Ossi Herrala, Panagiotis
  Astithas, Quentin Neill, Remi Lespinet, Sébastien Guimmara,
  and Thomas Schneider.

Returning contributors who helped this release are as follows.
Thanks for your continued support.

  Alex Henrie, brian m. carlson, Carlos Martín Nieto, Charles
  Bailey, David Aguilar, David Turner, Dennis Kaarsemaker,
  Elia Pinto, Eric Sunshine, Fredrik Gustafsson, Jean-Noel
  Avila, Jeff King, Jim Hill, Johannes Sixt, Jonathan Nieder,
  Junio C Hamano, Karthik Nayak, Luke Diamand, Matthieu Moy, Max
  Kirillov, Michael Coleman, Michael Haggerty, Michael J Gruber,
  Mike Hommey, Nguyễn Thái Ngọc Duy, Patrick Steinhardt, Paul
  Tan, Phil Hord, Phillip Sz, Ramsay Allan Jones, René Scharfe,
  Stefan Beller, SZEDER Gábor, Thomas Braun, Thomas Gummerer,
  Torsten Bögershausen, and Vitor Antunes.

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

Git 2.5 Release Notes (draft)
=============================

Updates since v2.4
------------------

UI, Workflows & Features

 * The bash completion script (in contrib/) learned a few options that
   "git revert" takes.

 * Whitespace breakages in deleted and context lines can also be
   painted in the output of "git diff" and friends with the new
   --ws-error-highlight option.

 * List of commands shown by "git help" are grouped along the workflow
   elements to help early learners.

 * "git p4" now detects the filetype (e.g. binary) correctly even when
   the files are opened exclusively.

 * git p4 attempts to better handle branches in Perforce.

 * "git p4" learned "--changes-block-size <n>" to read the changes in
   chunks from Perforce, instead of making one call to "p4 changes"
   that may trigger "too many rows scanned" error from Perforce.

 * More workaround for Perforce's row number limit in "git p4".

 * Unlike "$EDITOR" and "$GIT_EDITOR" that can hold the path to the
   command and initial options (e.g. "/path/to/emacs -nw"), 'git p4'
   did not let the shell interpolate the contents of the environment
   variable that name the editor "$P4EDITOR" (and "$EDITOR", too).
   This release makes it in line with the rest of Git, as well as with
   Perforce.

 * A new short-hand <branch>@{push} denotes the remote-tracking branch
   that tracks the branch at the remote the <branch> would be pushed
   to.

 * "git show-branch --topics HEAD" (with no other arguments) did not
   do anything interesting.  Instead, contrast the given revision
   against all the local branches by default.

 * A replacement for contrib/workdir/git-new-workdir that does not
   rely on symbolic links and make sharing of objects and refs safer
   by making the borrowee and borrowers aware of each other.

   Consider this as still an experimental feature; the UI will likely
   to change.

 * Tweak the sample "store" backend of the credential helper to honor
   XDG configuration file locations when specified.

 * A heuristic we use to catch mistyped paths on the command line
   "git <cmd> <revs> <pathspec>" is to make sure that all the non-rev
   parameters in the later part of the command line are names of the
   files in the working tree, but that means "git grep $str -- \*.c"
   must always be disambiguated with "--", because nobody sane will
   create a file whose name literally is asterisk-dot-see.  Loosen the
   heuristic to declare that with a wildcard string the user likely
   meant to give us a pathspec.

 * "git merge FETCH_HEAD" learned that the previous "git fetch" could
   be to create an Octopus merge, i.e. recording multiple branches
   that are not marked as "not-for-merge"; this allows us to lose an
   old style invocation "git merge <msg> HEAD $commits..." in the
   implementation of "git pull" script; the old style syntax can now
   be deprecated (but not removed yet).

 * Filter scripts were run with SIGPIPE disabled on the Git side,
   expecting that they may not read what Git feeds them to filter.
   We however treated a filter that does not read its input fully
   before exiting as an error.  We no longer do and ignore EPIPE
   when writing to feed the filter scripts.

   This changes semantics, but arguably in a good way.  If a filter
   can produce its output without fully consuming its input using
   whatever magic, we now let it do so, instead of diagnosing it
   as a programming error.

 * Instead of dying immediately upon failing to obtain a lock, the
   locking (of refs etc) retries after a short while with backoff.

 * Introduce http.<url>.SSLCipherList configuration variable to tweak
   the list of cipher suite to be used with libcURL when talking with
   https:// sites.

 * "git subtree" script (in contrib/) used "echo -n" to produce
   progress messages in a non-portable way.

 * "git subtree" script (in contrib/) does not have --squash option
   when pushing, but the documentation and help text pretended as if
   it did.

 * The Git subcommand completion (in contrib/) no longer lists credential
   helpers among candidates; they are not something the end user would
   invoke interactively.

 * The index file can be taught with "update-index --untracked-cache"
   to optionally remember already seen untracked files, in order to
   speed up "git status" in a working tree with tons of cruft.

 * "git mergetool" learned to drive WinMerge as a backend.

 * "git upload-pack" that serves "git fetch" can be told to serve
   commits that are not at the tip of any ref, as long as they are
   reachable from a ref, with uploadpack.allowReachableSHA1InWant
   configuration variable.

 * "git cat-file --batch(-check)" learned the "--follow-symlinks"
   option that follows an in-tree symbolic link when asked about an
   object via extended SHA-1 syntax, e.g. HEAD:RelNotes that points at
   Documentation/RelNotes/2.5.0.txt.  With the new option, the command
   behaves as if HEAD:Documentation/RelNotes/2.5.0.txt was given as
   input instead.

   Consider this as still an experimental and incomplete feature:

    - We may want to do the same for in-index objects, e.g.
      asking for :RelNotes with this option should give
      :Documentation/RelNotes/2.5.0.txt, too

    - "git cat-file --follow-symlinks blob HEAD:RelNotes"
      may also be something we want to allow in the future.

 * "git send-email" learned the alias file format used by the sendmail
   program (in a simplified form; we obviously do not feed pipes).

 * "git am" learned am.threeWay configuration variable.

 * Traditionally, external low-level 3-way merge drivers are expected
   to produce their results based solely on the contents of the three
   variants given in temporary files named by %O, %A and %B on their
   command line.  Additionally allow them to look at the final path
   (given by %P).

 * "git blame" learned blame.showEmail configuration variable.

 * "git apply" cannot diagnose a patch corruption when the breakage is
   to mark the length of the hunk shorter than it really is on the
   hunk header line "@@ -l,k +m,n @@"; one special case it could is
   when the hunk becomes no-op (e.g. k == n == 2 for two-line context
   patch output), and it learned to do so in this special case.

 * Add the "--allow-unknown-type" option to "cat-file" to allow
   inspecting loose objects of an experimental or a broken type.

 * Many long-running operations show progress eye-candy, even when
   they are later backgrounded.  Hide the eye-candy when the process
   is sent to the background instead.
   (merge a4fb76c lm/squelch-bg-progress later to maint).


Performance, Internal Implementation, Development Support etc.

 * "unsigned char [20]" used throughout the code to represent object
   names are being converted into a semi-opaque "struct object_id".
   This effort is expected to interfere with other topics in flight,
   but hopefully will give us one extra level of abstraction in the
   end, when completed.

 * for_each_ref() callback functions were taught to name the objects
   not with "unsigned char sha1[20]" but with "struct object_id".

 * Catch a programmer mistake to feed a pointer not an array to
   ARRAY_SIZE() macro, by using a couple of GCC extensions.

 * Some error messages in "git config" were emitted without calling
   the usual error() facility.

 * When "add--interactive" splits a hunk into two overlapping hunks
   and then let the user choose only one, it sometimes feeds an
   incorrect patch text to "git apply".  Add tests to demonstrate
   this.

   I have a slight suspicion that this may be $gmane/87202 coming back
   and biting us (I seem to have said "let's run with this and see
   what happens" back then).

 * More line-ending tests.

 * An earlier rewrite to use strbuf_getwholeline() instead of fgets(3)
   to read packed-refs file revealed that the former is unacceptably
   inefficient.  It has been optimized by using getdelim(3) when
   available.

 * The refs API uses ref_lock struct which had its own "int fd", even
   though the same file descriptor was in the lock struct it contains.
   Clean-up the code to lose this redundant field.

 * There was a dead code that used to handle "git pull --tags" and
   show special-cased error message, which was made irrelevant when
   the semantics of the option changed back in Git 1.9 days.
   (merge 19d122b pt/pull-tags-error-diag later to maint).

 * Help us to find broken test script that splits the body part of the
   test by mistaken use of wrong kind of quotes.
   (merge d93d5d5 jc/test-prereq-validate later to maint).

 * Developer support to automatically detect broken &&-chain in the
   test scripts is now turned on by default.
   (merge 92b269f jk/test-chain-lint later to maint).

 * Error reporting mechanism used in "refs" API has been made more
   consistent.

 * "git pull" has more test coverage now.

 * "git pull" has become more aware of the options meant for
   underlying "git fetch" and then learned to use parse-options
   parser.

Also contains various documentation updates and code clean-ups.


Fixes since v2.4
----------------

Unless otherwise noted, all the fixes since v2.4 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * Git 2.4 broke setting verbosity and progress levels on "git clone"
   with native transports.
   (merge 822f0c4 mh/clone-verbosity-fix later to maint).

 * "git add -e" did not allow the user to abort the operation by
   killing the editor.
   (merge cb64800 jk/add-e-kill-editor later to maint).

 * Memory usage of "git index-pack" has been trimmed by tens of
   per-cent.
   (merge f0e7f11 nd/slim-index-pack-memory-usage later to maint).

 * "git rev-list --objects $old --not --all" to see if everything that
   is reachable from $old is already connected to the existing refs
   was very inefficient.
   (merge b6e8a3b jk/still-interesting later to maint).

 * "hash-object --literally" introduced in v2.2 was not prepared to
   take a really long object type name.
   (merge 1427a7f jc/hash-object later to maint).

 * "git rebase --quiet" was not quite quiet when there is nothing to
   do.
   (merge 22946a9 jk/rebase-quiet-noop later to maint).

 * The completion for "log --decorate=" parameter value was incorrect.
   (merge af16bda sg/complete-decorate-full-not-long later to maint).

 * "filter-branch" corrupted commit log message that ends with an
   incomplete line on platforms with some "sed" implementations that
   munge such a line.  Work it around by avoiding to use "sed".
   (merge df06201 jk/filter-branch-use-of-sed-on-incomplete-line later to maint).

 * "git daemon" fails to build from the source under NO_IPV6
   configuration (regression in 2.4).
   (merge d358f77 jc/daemon-no-ipv6-for-2.4.1 later to maint).

 * Some time ago, "git blame" (incorrectly) lost the convert_to_git()
   call when synthesizing a fake "tip" commit that represents the
   state in the working tree, which broke folks who record the history
   with LF line ending to make their project portable across platforms
   while terminating lines in their working tree files with CRLF for
   their platform.
   (merge 4bf256d tb/blame-resurrect-convert-to-git later to maint).

 * We avoid setting core.worktree when the repository location is the
   ".git" directory directly at the top level of the working tree, but
   the code misdetected the case in which the working tree is at the
   root level of the filesystem (which arguably is a silly thing to
   do, but still valid).
   (merge 84ccad8 jk/init-core-worktree-at-root later to maint).

 * "git commit --date=now" or anything that relies on approxidate lost
   the daylight-saving-time offset.
   (merge f6e6362 jc/epochtime-wo-tz later to maint).

 * Access to objects in repositories that borrow from another one on a
   slow NFS server unnecessarily got more expensive due to recent code
   becoming more cautious in a naive way not to lose objects to pruning.
   (merge ee1c6c3 jk/prune-mtime later to maint).

 * The codepaths that read .gitignore and .gitattributes files have been
   taught that these files encoded in UTF-8 may have UTF-8 BOM marker at
   the beginning; this makes it in line with what we do for configuration
   files already.
   (merge 27547e5 cn/bom-in-gitignore later to maint).

 * a few helper scripts in the test suite did not report errors
   correctly.
   (merge de248e9 ep/fix-test-lib-functions-report later to maint).

 * The default $HOME/.gitconfig file created upon "git config --global"
   that edits it had incorrectly spelled user.name and user.email
   entries in it.
   (merge 7e11052 oh/fix-config-default-user-name-section later to maint).

 * "git cat-file bl $blob" failed to barf even though there is no
   object type that is "bl".
   (merge b7994af jk/type-from-string-gently later to maint).

 * The usual "git diff" when seeing a file turning into a directory
   showed a patchset to remove the file and create all files in the
   directory, but "git diff --no-index" simply refused to work.  Also,
   when asked to compare a file and a directory, imitate POSIX "diff"
   and compare the file with the file with the same name in the
   directory, instead of refusing to run.
   (merge 0615173 jc/diff-no-index-d-f later to maint).

 * "git rebase -i" moved the "current" command from "todo" to "done" a
   bit too prematurely, losing a step when a "pick" did not even start.
   (merge 8cbc57c ph/rebase-i-redo later to maint).

 * The connection initiation code for "ssh" transport tried to absorb
   differences between the stock "ssh" and Putty-supplied "plink" and
   its derivatives, but the logic to tell that we are using "plink"
   variants were too loose and falsely triggered when "plink" appeared
   anywhere in the path (e.g. "/home/me/bin/uplink/ssh").
   (merge baaf233 bc/connect-plink later to maint).

 * We have prepended $GIT_EXEC_PATH and the path "git" is installed in
   (typically "/usr/bin") to $PATH when invoking subprograms and hooks
   for almost eternity, but the original use case the latter tried to
   support was semi-bogus (i.e. install git to /opt/foo/git and run it
   without having /opt/foo on $PATH), and more importantly it has
   become less and less relevant as Git grew more mainstream (i.e. the
   users would _want_ to have it on their $PATH).  Stop prepending the
   path in which "git" is installed to users' $PATH, as that would
   interfere the command search order people depend on (e.g. they may
   not like versions of programs that are unrelated to Git in /usr/bin
   and want to override them by having different ones in /usr/local/bin
   and have the latter directory earlier in their $PATH).
   (merge a0b4507 jk/git-no-more-argv0-path-munging later to maint).

 * core.excludesfile (defaulting to $XDG_HOME/git/ignore) is supposed
   to be overridden by repository-specific .git/info/exclude file, but
   the order was swapped from the beginning. This belatedly fixes it.
   (merge 099d2d8 jc/gitignore-precedence later to maint).

 * There was a commented-out (instead of being marked to expect
   failure) test that documented a breakage that was fixed since the
   test was written; turn it into a proper test.
   (merge 66d2e04 sb/t1020-cleanup later to maint).

 * The "log --decorate" enhancement in Git 2.4 that shows the commit
   at the tip of the current branch e.g. "HEAD -> master", did not
   work with --decorate=full.
   (merge 429ad20 mg/log-decorate-HEAD later to maint).

 * The ref API did not handle cases where 'refs/heads/xyzzy/frotz' is
   removed at the same time as 'refs/heads/xyzzy' is added (or vice
   versa) very well.
   (merge c628edf mh/ref-directory-file later to maint).

 * Multi-ref transaction support we merged a few releases ago
   unnecessarily kept many file descriptors open, risking to fail with
   resource exhaustion.  This is for 2.4.x track.
   (merge 185ce3a mh/write-refs-sooner-2.4 later to maint).

 * "git bundle verify" did not diagnose extra parameters on the
   command line.
   (merge 7886cfa ps/bundle-verify-arg later to maint).

 * Various documentation mark-up fixes to make the output more
   consistent in general and also make AsciiDoctor (an alternative
   formatter) happier.
   (merge d0258b9 jk/asciidoc-markup-fix later to maint).
   (merge ad3967a jk/stripspace-asciidoctor-fix later to maint).
   (merge 975e382 ja/tutorial-asciidoctor-fix later to maint).

 * The code to read pack-bitmap wanted to allocate a few hundred
   pointers to a structure, but by mistake allocated and leaked memory
   enough to hold that many actual structures.  Correct the allocation
   size and also have it on stack, as it is small enough.
   (merge 599dc76 rs/plug-leak-in-pack-bitmaps later to maint).

 * The pull.ff configuration was supposed to override the merge.ff
   configuration, but it didn't.
   (merge db9bb28 pt/pull-ff-vs-merge-ff later to maint).

 * "git pull --log" and "git pull --no-log" worked as expected, but
   "git pull --log=20" did not.
   (merge 5061a44 pt/pull-log-n later to maint).

 * "git rerere forget" in a repository without rerere enabled gave a
   cryptic error message; it should be a silent no-op instead.
   (merge 0544574 jk/rerere-forget-check-enabled later to maint).

 * "git rebase -i" fired post-rewrite hook when it shouldn't (namely,
   when it was told to stop sequencing with 'exec' insn).
   (merge 141ff8f mm/rebase-i-post-rewrite-exec later to maint).

 * Clarify that "log --raw" and "log --format=raw" are unrelated
   concepts.
   (merge 92de921 mm/log-format-raw-doc later to maint).

 * Make "git stash something --help" error out, so that users can
   safely say "git stash drop --help".
   (merge 5ba2831 jk/stash-options later to maint).

 * The clean/smudge interface did not work well when filtering an
   empty contents (failed and then passed the empty input through).
   It can be argued that a filter that produces anything but empty for
   an empty input is nonsense, but if the user wants to do strange
   things, then why not?
   (merge f6a1e1e jh/filter-empty-contents later to maint).

 * Communication between the HTTP server and http_backend process can
   lead to a dead-lock when relaying a large ref negotiation request.
   Diagnose the situation better, and mitigate it by reading such a
   request first into core (to a reasonable limit).
   (merge 636614f jk/http-backend-deadlock later to maint).

 * "git clean pathspec..." tried to lstat(2) and complain even for
   paths outside the given pathspec.
   (merge 838d6a9 dt/clean-pathspec-filter-then-lstat later to maint).

 * Recent "git prune" traverses young unreachable objects to safekeep
   old objects in the reachability chain from them, which sometimes
   caused error messages that are unnecessarily alarming.
   (merge ce4e7b2 jk/squelch-missing-link-warning-for-unreachable later to maint).

 * The configuration reader/writer uses mmap(2) interface to access
   the files; when we find a directory, it barfed with "Out of memory?".
   (merge 9ca0aaf jk/diagnose-config-mmap-failure later to maint).

 * "color.diff.plain" was a misnomer; give it 'color.diff.context' as
   a more logical synonym.
   (merge 8dbf3eb jk/color-diff-plain-is-context later to maint).

 * The setup code used to die when core.bare and core.worktree are set
   inconsistently, even for commands that do not need working tree.
   (merge fada767 jk/die-on-bogus-worktree-late later to maint).

 * Recent Mac OS X updates breaks the logic to detect that the machine
   is on the AC power in the sample pre-auto-gc script.
   (merge c54c7b3 pa/auto-gc-mac-osx later to maint).

 * "git commit --cleanup=scissors" was not careful enough to protect
   against getting fooled by a line that looked like scissors.
   (merge fbfa097 sg/commit-cleanup-scissors later to maint).

 * "Have we lost a race with competing repack?" check was too
   expensive, especially while receiving a huge object transfer
   that runs index-pack (e.g. "clone" or "fetch").
   (merge 0eeb077 jk/index-pack-reduce-recheck later to maint).

 * The tcsh completion writes a bash scriptlet but that would have
   failed for users with noclobber set.
   (merge 0b1f688 af/tcsh-completion-noclobber later to maint).

 * "git for-each-ref" reported "missing object" for 0{40} when it
   encounters a broken ref.  The lack of object whose name is 0{40} is
   not the problem; the ref being broken is.
   (merge 501cf47 mh/reporting-broken-refs-from-for-each-ref later to maint).

 * Various fixes around "git am" that applies a patch to a history
   that is not there yet.
   (merge 6ea3b67 pt/am-abort-fix later to maint).

 * "git fsck" used to ignore missing or invalid objects recorded in reflog.
   (merge 19bf6c9 mh/fsck-reflog-entries later to maint).

 * "git format-patch --ignore-if-upstream A..B" did not like to be fed
   tags as boundary commits.
   (merge 9b7a61d jc/do-not-feed-tags-to-clear-commit-marks later to maint).

 * Code cleanups and documentation updates.
   (merge 0269f96 mm/usage-log-l-can-take-regex later to maint).
   (merge 64f2589 nd/t1509-chroot-test later to maint).
   (merge d201a1e sb/test-bitmap-free-at-end later to maint).
   (merge 05bfc7d sb/line-log-plug-pairdiff-leak later to maint).
   (merge 846e5df pt/xdg-config-path later to maint).
   (merge 1154aa4 jc/plug-fmt-merge-msg-leak later to maint).
   (merge 319b678 jk/sha1-file-reduce-useless-warnings later to maint).
   (merge 9a35c14 fg/document-commit-message-stripping later to maint).
   (merge bbf431c ps/doc-packfile-vs-pack-file later to maint).
   (merge 309a9e3 jk/skip-http-tests-under-no-curl later to maint).
   (merge ccd593c dl/branch-error-message later to maint).
   (merge 22570b6 rs/janitorial later to maint).
   (merge 5c2a581 mc/commit-doc-grammofix later to maint).
   (merge ce41720 ah/usage-strings later to maint).
   (merge e6a268c sb/glossary-submodule later to maint).
   (merge ec48a76 sb/submodule-doc-intro later to maint).
   (merge 14f8b9b jk/clone-dissociate later to maint).
   (merge 055c7e9 sb/pack-protocol-mention-smart-http later to maint).
   (merge 7c37a5d jk/make-fix-dependencies later to maint).
   (merge fc0aa39 sg/merge-summary-config later to maint).
   (merge 329af6c pt/t0302-needs-sanity later to maint).
   (merge d614f07 fk/doc-format-patch-vn later to maint).
   (merge 72dbb36 sg/completion-commit-cleanup later to maint).
   (merge e654eb2 es/utf8-stupid-compiler-workaround later to maint).
   (merge 34b935c es/osx-header-pollutes-mask-macro later to maint).

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

Changes since v2.4.0 are a bit too numerous to list.

^ permalink raw reply	[relevance 1%]

* [ANNOUNCE] Git v2.5.0-rc2
@ 2015-07-13 21:52  1% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-07-13 21:52 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate Git v2.5.0-rc2 is now available for testing
at the usual places.  It is comprised of 552 non-merge commits
since v2.4.0, contributed by 63 people, 21 of which are new faces.

To avoid user-facing interface to a new experimental feature that
replaces contrib/workdir after the release, I've merged another
topic to move that feature to "git worktree add", which is going to
be its final location.  We'll need to extend the pre-release freeze
a bit longer than we originally planned to make sure we have a
reasonably solid 2.5 final.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/testing/

The following public repositories all have a copy of the
'v2.5.0-rc2' tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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

New contributors whose contributions weren't in v2.4.0 are as follows.
Welcome to the Git development community!

  Allen Hubbe, Ariel Faigon, Blair Holloway, Christian Neukirchen,
  Danny Lin, Enrique Tobis, Frans Klaver, Fredrik Medley, Joe
  Cridge, Lars Kellogg-Stedman, Lawrence Siebert, Lex Spoon, Luke
  Mewburn, Miguel Torroja, Mike Edgar, Ossi Herrala, Panagiotis
  Astithas, Quentin Neill, Remi Lespinet, Sébastien Guimmara,
  and Thomas Schneider.

Returning contributors who helped this release are as follows.
Thanks for your continued support.

  Alex Henrie, brian m. carlson, Carlos Martín Nieto, Charles
  Bailey, Clemens Buchacher, David Aguilar, David Turner, Dennis
  Kaarsemaker, Elia Pinto, Eric Sunshine, Fredrik Gustafsson,
  Jean-Noel Avila, Jeff King, Jim Hill, Johannes Schindelin,
  Johannes Sixt, Jonathan Nieder, Junio C Hamano, Karsten Blees,
  Karthik Nayak, Luke Diamand, Matthieu Moy, Max Kirillov, Michael
  Coleman, Michael Haggerty, Michael J Gruber, Mike Hommey,
  Nguyễn Thái Ngọc Duy, Patrick Steinhardt, Paul Tan, Phil
  Hord, Phillip Sz, Ramsay Allan Jones, René Scharfe, Richard
  Hansen, Sebastian Schuberth, Stefan Beller, SZEDER Gábor, Thomas
  Braun, Thomas Gummerer, Torsten Bögershausen, and Vitor Antunes.

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

Git 2.5 Release Notes (draft)
=============================

Updates since v2.4
------------------

UI, Workflows & Features

 * The bash completion script (in contrib/) learned a few options that
   "git revert" takes.

 * Whitespace breakages in deleted and context lines can also be
   painted in the output of "git diff" and friends with the new
   --ws-error-highlight option.

 * List of commands shown by "git help" are grouped along the workflow
   elements to help early learners.

 * "git p4" now detects the filetype (e.g. binary) correctly even when
   the files are opened exclusively.

 * git p4 attempts to better handle branches in Perforce.

 * "git p4" learned "--changes-block-size <n>" to read the changes in
   chunks from Perforce, instead of making one call to "p4 changes"
   that may trigger "too many rows scanned" error from Perforce.

 * More workaround for Perforce's row number limit in "git p4".

 * Unlike "$EDITOR" and "$GIT_EDITOR" that can hold the path to the
   command and initial options (e.g. "/path/to/emacs -nw"), 'git p4'
   did not let the shell interpolate the contents of the environment
   variable that name the editor "$P4EDITOR" (and "$EDITOR", too).
   This release makes it in line with the rest of Git, as well as with
   Perforce.

 * A new short-hand <branch>@{push} denotes the remote-tracking branch
   that tracks the branch at the remote the <branch> would be pushed
   to.

 * "git show-branch --topics HEAD" (with no other arguments) did not
   do anything interesting.  Instead, contrast the given revision
   against all the local branches by default.

 * A replacement for contrib/workdir/git-new-workdir that does not
   rely on symbolic links and make sharing of objects and refs safer
   by making the borrowee and borrowers aware of each other.

   Consider this as still an experimental feature; its UI is still
   likely to change.

 * Tweak the sample "store" backend of the credential helper to honor
   XDG configuration file locations when specified.

 * A heuristic we use to catch mistyped paths on the command line
   "git <cmd> <revs> <pathspec>" is to make sure that all the non-rev
   parameters in the later part of the command line are names of the
   files in the working tree, but that means "git grep $str -- \*.c"
   must always be disambiguated with "--", because nobody sane will
   create a file whose name literally is asterisk-dot-see.  Loosen the
   heuristic to declare that with a wildcard string the user likely
   meant to give us a pathspec.

 * "git merge FETCH_HEAD" learned that the previous "git fetch" could
   be to create an Octopus merge, i.e. recording multiple branches
   that are not marked as "not-for-merge"; this allows us to lose an
   old style invocation "git merge <msg> HEAD $commits..." in the
   implementation of "git pull" script; the old style syntax can now
   be deprecated (but not removed yet).

 * Filter scripts were run with SIGPIPE disabled on the Git side,
   expecting that they may not read what Git feeds them to filter.
   We however treated a filter that does not read its input fully
   before exiting as an error.  We no longer do and ignore EPIPE
   when writing to feed the filter scripts.

   This changes semantics, but arguably in a good way.  If a filter
   can produce its output without fully consuming its input using
   whatever magic, we now let it do so, instead of diagnosing it
   as a programming error.

 * Instead of dying immediately upon failing to obtain a lock, the
   locking (of refs etc) retries after a short while with backoff.

 * Introduce http.<url>.SSLCipherList configuration variable to tweak
   the list of cipher suite to be used with libcURL when talking with
   https:// sites.

 * "git subtree" script (in contrib/) used "echo -n" to produce
   progress messages in a non-portable way.

 * "git subtree" script (in contrib/) does not have --squash option
   when pushing, but the documentation and help text pretended as if
   it did.

 * The Git subcommand completion (in contrib/) no longer lists credential
   helpers among candidates; they are not something the end user would
   invoke interactively.

 * The index file can be taught with "update-index --untracked-cache"
   to optionally remember already seen untracked files, in order to
   speed up "git status" in a working tree with tons of cruft.

 * "git mergetool" learned to drive WinMerge as a backend.

 * "git upload-pack" that serves "git fetch" can be told to serve
   commits that are not at the tip of any ref, as long as they are
   reachable from a ref, with uploadpack.allowReachableSHA1InWant
   configuration variable.

 * "git cat-file --batch(-check)" learned the "--follow-symlinks"
   option that follows an in-tree symbolic link when asked about an
   object via extended SHA-1 syntax, e.g. HEAD:RelNotes that points at
   Documentation/RelNotes/2.5.0.txt.  With the new option, the command
   behaves as if HEAD:Documentation/RelNotes/2.5.0.txt was given as
   input instead.

   Consider this as still an experimental and incomplete feature:

    - We may want to do the same for in-index objects, e.g.
      asking for :RelNotes with this option should give
      :Documentation/RelNotes/2.5.0.txt, too

    - "git cat-file --follow-symlinks blob HEAD:RelNotes"
      may also be something we want to allow in the future.

 * "git send-email" learned the alias file format used by the sendmail
   program (in a simplified form; we obviously do not feed pipes).

 * "git am" learned am.threeWay configuration variable.

 * Traditionally, external low-level 3-way merge drivers are expected
   to produce their results based solely on the contents of the three
   variants given in temporary files named by %O, %A and %B on their
   command line.  Additionally allow them to look at the final path
   (given by %P).

 * "git blame" learned blame.showEmail configuration variable.

 * "git apply" cannot diagnose a patch corruption when the breakage is
   to mark the length of the hunk shorter than it really is on the
   hunk header line "@@ -l,k +m,n @@"; one special case it could is
   when the hunk becomes no-op (e.g. k == n == 2 for two-line context
   patch output), and it learned to do so in this special case.

 * Add the "--allow-unknown-type" option to "cat-file" to allow
   inspecting loose objects of an experimental or a broken type.

 * Many long-running operations show progress eye-candy, even when
   they are later backgrounded.  Hide the eye-candy when the process
   is sent to the background instead.
   (merge a4fb76c lm/squelch-bg-progress later to maint).


Performance, Internal Implementation, Development Support etc.

 * "unsigned char [20]" used throughout the code to represent object
   names are being converted into a semi-opaque "struct object_id".
   This effort is expected to interfere with other topics in flight,
   but hopefully will give us one extra level of abstraction in the
   end, when completed.

 * for_each_ref() callback functions were taught to name the objects
   not with "unsigned char sha1[20]" but with "struct object_id".

 * Catch a programmer mistake to feed a pointer not an array to
   ARRAY_SIZE() macro, by using a couple of GCC extensions.

 * Some error messages in "git config" were emitted without calling
   the usual error() facility.

 * When "add--interactive" splits a hunk into two overlapping hunks
   and then let the user choose only one, it sometimes feeds an
   incorrect patch text to "git apply".  Add tests to demonstrate
   this.

   I have a slight suspicion that this may be $gmane/87202 coming back
   and biting us (I seem to have said "let's run with this and see
   what happens" back then).

 * More line-ending tests.

 * An earlier rewrite to use strbuf_getwholeline() instead of fgets(3)
   to read packed-refs file revealed that the former is unacceptably
   inefficient.  It has been optimized by using getdelim(3) when
   available.

 * The refs API uses ref_lock struct which had its own "int fd", even
   though the same file descriptor was in the lock struct it contains.
   Clean-up the code to lose this redundant field.

 * There was a dead code that used to handle "git pull --tags" and
   show special-cased error message, which was made irrelevant when
   the semantics of the option changed back in Git 1.9 days.
   (merge 19d122b pt/pull-tags-error-diag later to maint).

 * Help us to find broken test script that splits the body part of the
   test by mistaken use of wrong kind of quotes.
   (merge d93d5d5 jc/test-prereq-validate later to maint).

 * Developer support to automatically detect broken &&-chain in the
   test scripts is now turned on by default.
   (merge 92b269f jk/test-chain-lint later to maint).

 * Error reporting mechanism used in "refs" API has been made more
   consistent.

 * "git pull" has more test coverage now.

 * "git pull" has become more aware of the options meant for
   underlying "git fetch" and then learned to use parse-options
   parser.

 * Clarify in the Makefile a guideline to decide use of USE_NSEC.

Also contains various documentation updates and code clean-ups.


Fixes since v2.4
----------------

Unless otherwise noted, all the fixes since v2.4 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * Git 2.4 broke setting verbosity and progress levels on "git clone"
   with native transports.
   (merge 822f0c4 mh/clone-verbosity-fix later to maint).

 * "git add -e" did not allow the user to abort the operation by
   killing the editor.
   (merge cb64800 jk/add-e-kill-editor later to maint).

 * Memory usage of "git index-pack" has been trimmed by tens of
   per-cent.
   (merge f0e7f11 nd/slim-index-pack-memory-usage later to maint).

 * "git rev-list --objects $old --not --all" to see if everything that
   is reachable from $old is already connected to the existing refs
   was very inefficient.
   (merge b6e8a3b jk/still-interesting later to maint).

 * "hash-object --literally" introduced in v2.2 was not prepared to
   take a really long object type name.
   (merge 1427a7f jc/hash-object later to maint).

 * "git rebase --quiet" was not quite quiet when there is nothing to
   do.
   (merge 22946a9 jk/rebase-quiet-noop later to maint).

 * The completion for "log --decorate=" parameter value was incorrect.
   (merge af16bda sg/complete-decorate-full-not-long later to maint).

 * "filter-branch" corrupted commit log message that ends with an
   incomplete line on platforms with some "sed" implementations that
   munge such a line.  Work it around by avoiding to use "sed".
   (merge df06201 jk/filter-branch-use-of-sed-on-incomplete-line later to maint).

 * "git daemon" fails to build from the source under NO_IPV6
   configuration (regression in 2.4).
   (merge d358f77 jc/daemon-no-ipv6-for-2.4.1 later to maint).

 * Some time ago, "git blame" (incorrectly) lost the convert_to_git()
   call when synthesizing a fake "tip" commit that represents the
   state in the working tree, which broke folks who record the history
   with LF line ending to make their project portable across platforms
   while terminating lines in their working tree files with CRLF for
   their platform.
   (merge 4bf256d tb/blame-resurrect-convert-to-git later to maint).

 * We avoid setting core.worktree when the repository location is the
   ".git" directory directly at the top level of the working tree, but
   the code misdetected the case in which the working tree is at the
   root level of the filesystem (which arguably is a silly thing to
   do, but still valid).
   (merge 84ccad8 jk/init-core-worktree-at-root later to maint).

 * "git commit --date=now" or anything that relies on approxidate lost
   the daylight-saving-time offset.
   (merge f6e6362 jc/epochtime-wo-tz later to maint).

 * Access to objects in repositories that borrow from another one on a
   slow NFS server unnecessarily got more expensive due to recent code
   becoming more cautious in a naive way not to lose objects to pruning.
   (merge ee1c6c3 jk/prune-mtime later to maint).

 * The codepaths that read .gitignore and .gitattributes files have been
   taught that these files encoded in UTF-8 may have UTF-8 BOM marker at
   the beginning; this makes it in line with what we do for configuration
   files already.
   (merge 27547e5 cn/bom-in-gitignore later to maint).

 * a few helper scripts in the test suite did not report errors
   correctly.
   (merge de248e9 ep/fix-test-lib-functions-report later to maint).

 * The default $HOME/.gitconfig file created upon "git config --global"
   that edits it had incorrectly spelled user.name and user.email
   entries in it.
   (merge 7e11052 oh/fix-config-default-user-name-section later to maint).

 * "git cat-file bl $blob" failed to barf even though there is no
   object type that is "bl".
   (merge b7994af jk/type-from-string-gently later to maint).

 * The usual "git diff" when seeing a file turning into a directory
   showed a patchset to remove the file and create all files in the
   directory, but "git diff --no-index" simply refused to work.  Also,
   when asked to compare a file and a directory, imitate POSIX "diff"
   and compare the file with the file with the same name in the
   directory, instead of refusing to run.
   (merge 0615173 jc/diff-no-index-d-f later to maint).

 * "git rebase -i" moved the "current" command from "todo" to "done" a
   bit too prematurely, losing a step when a "pick" did not even start.
   (merge 8cbc57c ph/rebase-i-redo later to maint).

 * The connection initiation code for "ssh" transport tried to absorb
   differences between the stock "ssh" and Putty-supplied "plink" and
   its derivatives, but the logic to tell that we are using "plink"
   variants were too loose and falsely triggered when "plink" appeared
   anywhere in the path (e.g. "/home/me/bin/uplink/ssh").
   (merge baaf233 bc/connect-plink later to maint).

 * We have prepended $GIT_EXEC_PATH and the path "git" is installed in
   (typically "/usr/bin") to $PATH when invoking subprograms and hooks
   for almost eternity, but the original use case the latter tried to
   support was semi-bogus (i.e. install git to /opt/foo/git and run it
   without having /opt/foo on $PATH), and more importantly it has
   become less and less relevant as Git grew more mainstream (i.e. the
   users would _want_ to have it on their $PATH).  Stop prepending the
   path in which "git" is installed to users' $PATH, as that would
   interfere the command search order people depend on (e.g. they may
   not like versions of programs that are unrelated to Git in /usr/bin
   and want to override them by having different ones in /usr/local/bin
   and have the latter directory earlier in their $PATH).
   (merge a0b4507 jk/git-no-more-argv0-path-munging later to maint).

 * core.excludesfile (defaulting to $XDG_HOME/git/ignore) is supposed
   to be overridden by repository-specific .git/info/exclude file, but
   the order was swapped from the beginning. This belatedly fixes it.
   (merge 099d2d8 jc/gitignore-precedence later to maint).

 * There was a commented-out (instead of being marked to expect
   failure) test that documented a breakage that was fixed since the
   test was written; turn it into a proper test.
   (merge 66d2e04 sb/t1020-cleanup later to maint).

 * The "log --decorate" enhancement in Git 2.4 that shows the commit
   at the tip of the current branch e.g. "HEAD -> master", did not
   work with --decorate=full.
   (merge 429ad20 mg/log-decorate-HEAD later to maint).

 * The ref API did not handle cases where 'refs/heads/xyzzy/frotz' is
   removed at the same time as 'refs/heads/xyzzy' is added (or vice
   versa) very well.
   (merge c628edf mh/ref-directory-file later to maint).

 * Multi-ref transaction support we merged a few releases ago
   unnecessarily kept many file descriptors open, risking to fail with
   resource exhaustion.  This is for 2.4.x track.
   (merge 185ce3a mh/write-refs-sooner-2.4 later to maint).

 * "git bundle verify" did not diagnose extra parameters on the
   command line.
   (merge 7886cfa ps/bundle-verify-arg later to maint).

 * Various documentation mark-up fixes to make the output more
   consistent in general and also make AsciiDoctor (an alternative
   formatter) happier.
   (merge d0258b9 jk/asciidoc-markup-fix later to maint).
   (merge ad3967a jk/stripspace-asciidoctor-fix later to maint).
   (merge 975e382 ja/tutorial-asciidoctor-fix later to maint).

 * The code to read pack-bitmap wanted to allocate a few hundred
   pointers to a structure, but by mistake allocated and leaked memory
   enough to hold that many actual structures.  Correct the allocation
   size and also have it on stack, as it is small enough.
   (merge 599dc76 rs/plug-leak-in-pack-bitmaps later to maint).

 * The pull.ff configuration was supposed to override the merge.ff
   configuration, but it didn't.
   (merge db9bb28 pt/pull-ff-vs-merge-ff later to maint).

 * "git pull --log" and "git pull --no-log" worked as expected, but
   "git pull --log=20" did not.
   (merge 5061a44 pt/pull-log-n later to maint).

 * "git rerere forget" in a repository without rerere enabled gave a
   cryptic error message; it should be a silent no-op instead.
   (merge 0544574 jk/rerere-forget-check-enabled later to maint).

 * "git rebase -i" fired post-rewrite hook when it shouldn't (namely,
   when it was told to stop sequencing with 'exec' insn).
   (merge 141ff8f mm/rebase-i-post-rewrite-exec later to maint).

 * Clarify that "log --raw" and "log --format=raw" are unrelated
   concepts.
   (merge 92de921 mm/log-format-raw-doc later to maint).

 * Make "git stash something --help" error out, so that users can
   safely say "git stash drop --help".
   (merge 5ba2831 jk/stash-options later to maint).

 * The clean/smudge interface did not work well when filtering an
   empty contents (failed and then passed the empty input through).
   It can be argued that a filter that produces anything but empty for
   an empty input is nonsense, but if the user wants to do strange
   things, then why not?
   (merge f6a1e1e jh/filter-empty-contents later to maint).

 * Communication between the HTTP server and http_backend process can
   lead to a dead-lock when relaying a large ref negotiation request.
   Diagnose the situation better, and mitigate it by reading such a
   request first into core (to a reasonable limit).
   (merge 636614f jk/http-backend-deadlock later to maint).

 * "git clean pathspec..." tried to lstat(2) and complain even for
   paths outside the given pathspec.
   (merge 838d6a9 dt/clean-pathspec-filter-then-lstat later to maint).

 * Recent "git prune" traverses young unreachable objects to safekeep
   old objects in the reachability chain from them, which sometimes
   caused error messages that are unnecessarily alarming.
   (merge ce4e7b2 jk/squelch-missing-link-warning-for-unreachable later to maint).

 * The configuration reader/writer uses mmap(2) interface to access
   the files; when we find a directory, it barfed with "Out of memory?".
   (merge 9ca0aaf jk/diagnose-config-mmap-failure later to maint).

 * "color.diff.plain" was a misnomer; give it 'color.diff.context' as
   a more logical synonym.
   (merge 8dbf3eb jk/color-diff-plain-is-context later to maint).

 * The setup code used to die when core.bare and core.worktree are set
   inconsistently, even for commands that do not need working tree.
   (merge fada767 jk/die-on-bogus-worktree-late later to maint).

 * Recent Mac OS X updates breaks the logic to detect that the machine
   is on the AC power in the sample pre-auto-gc script.
   (merge c54c7b3 pa/auto-gc-mac-osx later to maint).

 * "git commit --cleanup=scissors" was not careful enough to protect
   against getting fooled by a line that looked like scissors.
   (merge fbfa097 sg/commit-cleanup-scissors later to maint).

 * "Have we lost a race with competing repack?" check was too
   expensive, especially while receiving a huge object transfer
   that runs index-pack (e.g. "clone" or "fetch").
   (merge 0eeb077 jk/index-pack-reduce-recheck later to maint).

 * The tcsh completion writes a bash scriptlet but that would have
   failed for users with noclobber set.
   (merge 0b1f688 af/tcsh-completion-noclobber later to maint).

 * "git for-each-ref" reported "missing object" for 0{40} when it
   encounters a broken ref.  The lack of object whose name is 0{40} is
   not the problem; the ref being broken is.
   (merge 501cf47 mh/reporting-broken-refs-from-for-each-ref later to maint).

 * Various fixes around "git am" that applies a patch to a history
   that is not there yet.
   (merge 6ea3b67 pt/am-abort-fix later to maint).

 * "git fsck" used to ignore missing or invalid objects recorded in reflog.
   (merge 19bf6c9 mh/fsck-reflog-entries later to maint).

 * "git format-patch --ignore-if-upstream A..B" did not like to be fed
   tags as boundary commits.
   (merge 9b7a61d jc/do-not-feed-tags-to-clear-commit-marks later to maint).

 * "git fetch --depth=<depth>" and "git clone --depth=<depth>" issued
   a shallow transfer request even to an upload-pack that does not
   support the capability.
   (merge eb86a50 me/fetch-into-shallow-safety later to maint).

 * "git rebase" did not exit with failure when format-patch it invoked
   failed for whatever reason.
   (merge 60d708b cb/rebase-am-exit-code later to maint).

 * Fix a small bug in our use of umask() return value.
   (merge 3096b2e jk/fix-refresh-utime later to maint).

 * An ancient test framework enhancement to allow color was not
   entirely correct; this makes it work even when tput needs to read
   from the ~/.terminfo under the user's real HOME directory.
   (merge d5c1b7c rh/test-color-avoid-terminfo-in-original-home later to maint).

 * A minor bugfix when pack bitmap is used with "rev-list --count".
   (merge c8a70d3 jk/rev-list-no-bitmap-while-pruning later to maint).

 * "git config" failed to update the configuration file when the
   underlying filesystem is incapable of renaming a file that is still
   open.
   (merge 7a64592 kb/config-unmap-before-renaming later to maint).

 * Avoid possible ssize_t to int truncation.
   (merge 6c8afe4 mh/strbuf-read-file-returns-ssize-t later to maint).

 * When you say "!<ENTER>" while running say "git log", you'd confuse
   yourself in the resulting shell, that may look as if you took
   control back to the original shell you spawned "git log" from but
   that isn't what is happening.  To that new shell, we leaked
   GIT_PAGER_IN_USE environment variable that was meant as a local
   communication between the original "Git" and subprocesses that was
   spawned by it after we launched the pager, which caused many
   "interesting" things to happen, e.g. "git diff | cat" still paints
   its output in color by default.

   Stop leaking that environment variable to the pager's half of the
   fork; we only need it on "Git" side when we spawn the pager.
   (merge 124b519 jc/unexport-git-pager-in-use-in-pager later to maint).

 * Abandoning an already applied change in "git rebase -i" with
   "--continue" left CHERRY_PICK_HEAD and confused later steps.
   (merge 0e0aff4 js/rebase-i-clean-up-upon-continue-to-skip later to maint).

 * We used to ask libCURL to use the most secure authentication method
   available when talking to an HTTP proxy only when we were told to
   talk to one via configuration variables.  We now ask libCURL to
   always use the most secure authentication method, because the user
   can tell libCURL to use an HTTP proxy via an environment variable
   without using configuration variables.
   (merge 5841520 et/http-proxyauth later to maint).

 * A fix to a minor regression to "git fsck" in v2.2 era that started
   complaining about a body-less tag object when it lacks a separator
   empty line after its header to separate it with a non-existent body.
   (merge 84d18c0 jc/fsck-retire-require-eoh later to maint).

 * Code cleanups and documentation updates.
   (merge 0269f96 mm/usage-log-l-can-take-regex later to maint).
   (merge 64f2589 nd/t1509-chroot-test later to maint).
   (merge d201a1e sb/test-bitmap-free-at-end later to maint).
   (merge 05bfc7d sb/line-log-plug-pairdiff-leak later to maint).
   (merge 846e5df pt/xdg-config-path later to maint).
   (merge 1154aa4 jc/plug-fmt-merge-msg-leak later to maint).
   (merge 319b678 jk/sha1-file-reduce-useless-warnings later to maint).
   (merge 9a35c14 fg/document-commit-message-stripping later to maint).
   (merge bbf431c ps/doc-packfile-vs-pack-file later to maint).
   (merge 309a9e3 jk/skip-http-tests-under-no-curl later to maint).
   (merge ccd593c dl/branch-error-message later to maint).
   (merge 22570b6 rs/janitorial later to maint).
   (merge 5c2a581 mc/commit-doc-grammofix later to maint).
   (merge ce41720 ah/usage-strings later to maint).
   (merge e6a268c sb/glossary-submodule later to maint).
   (merge ec48a76 sb/submodule-doc-intro later to maint).
   (merge 14f8b9b jk/clone-dissociate later to maint).
   (merge 055c7e9 sb/pack-protocol-mention-smart-http later to maint).
   (merge 7c37a5d jk/make-fix-dependencies later to maint).
   (merge fc0aa39 sg/merge-summary-config later to maint).
   (merge 329af6c pt/t0302-needs-sanity later to maint).
   (merge d614f07 fk/doc-format-patch-vn later to maint).
   (merge 72dbb36 sg/completion-commit-cleanup later to maint).
   (merge e654eb2 es/utf8-stupid-compiler-workaround later to maint).
   (merge 34b935c es/osx-header-pollutes-mask-macro later to maint).
   (merge ab7fade jc/prompt-document-ps1-state-separator later to maint).
   (merge 25f600e mm/describe-doc later to maint).
   (merge 83fe167 mm/branch-doc-updates later to maint).
   (merge 75d2e5a ls/hint-rev-list-count later to maint).
   (merge edc8f71 cb/subtree-tests-update later to maint).
   (merge 5330e6e sb/p5310-and-chain later to maint).
   (merge c4ac525 tb/checkout-doc later to maint).
   (merge e479c5f jk/pretty-encoding-doc later to maint).
   (merge 7e837c6 ss/clone-guess-dir-name-simplify later to maint).

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

Changes since v2.5.0-rc1 are as follows:

Charles Bailey (3):
      contrib/subtree: use tabs consitently for indentation in tests
      contrib/subtree: fix broken &&-chains and revealed test error
      contrib/subtree: small tidy-up to test

Clemens Buchacher (1):
      rebase: return non-zero error code if format-patch fails

Enrique Tobis (1):
      http: always use any proxy auth method available

Eric Sunshine (23):
      Documentation/git-checkout: fix incorrect worktree prune command
      Documentation/git-worktree: associate options with commands
      Documentation: move linked worktree description from checkout to worktree
      Documentation/git-worktree: add BUGS section
      Documentation/git-worktree: split technical info from general description
      Documentation/git-worktree: add high-level 'lock' overview
      Documentation/git-worktree: add EXAMPLES section
      checkout: fix bug with --to and relative HEAD
      checkout: relocate --to's "no branch specified" check
      checkout: prepare_linked_checkout: drop now-unused 'new' argument
      checkout: make --to unconditionally verbose
      checkout: drop 'checkout_opts' dependency from prepare_linked_checkout
      worktree: introduce "add" command
      worktree: add --force option
      worktree: add --detach option
      worktree: add -b/-B options
      tests: worktree: retrofit "checkout --to" tests for "worktree add"
      checkout: retire --to option
      checkout: require worktree unconditionally
      worktree: extract basename computation to new function
      worktree: add: make -b/-B default to HEAD when <branch> is omitted
      worktree: add: auto-vivify new branch when <branch> is omitted
      checkout: retire --ignore-other-worktrees in favor of --force

Jeff King (4):
      docs: clarify that --encoding can produce invalid sequences
      for_each_packed_object: automatically open pack index
      rev-list: disable --use-bitmap-index when pruning commits
      check_and_freshen_file: fix reversed success-check

Johannes Schindelin (2):
      t3404: demonstrate CHERRY_PICK_HEAD bug
      rebase -i: do not leave a CHERRY_PICK_HEAD file behind

Junio C Hamano (6):
      fsck: it is OK for a tag and a commit to lack the body
      pager: do not leak "GIT_PAGER_IN_USE" to the pager
      index-pack: fix allocation of sorted_by_pos array
      The last minute bits of fixes
      Revert "checkout: retire --ignore-other-worktrees in favor of --force"
      Git 2.5.0-rc2

Karsten Blees (2):
      config.c: fix writing config files on Windows network shares
      Makefile / racy-git.txt: clarify USE_NSEC prerequisites

Lawrence Siebert (1):
      rev-list: add --count to usage guide

Matthieu Moy (3):
      git-multimail: update to release 1.1.1
      Documentation/branch: document -d --force and -m --force
      Documentation/branch: document -M and -D in terms of --force

Michael Haggerty (1):
      strbuf: strbuf_read_file() should return ssize_t

Nguyễn Thái Ngọc Duy (3):
      checkout: don't check worktrees when not necessary
      worktree: new place for "git prune --worktrees"
      Add tests for wildcard "path vs ref" disambiguation

Richard Hansen (2):
      Revert "test-lib.sh: do tests for color support after changing HOME"
      test-lib.sh: fix color support when tput needs ~/.terminfo

Sebastian Schuberth (1):
      clone: simplify string handling in guess_dir_name()

Stefan Beller (1):
      p5310: Fix broken && chain in performance test

Torsten Bögershausen (1):
      git-checkout.txt: document "git checkout <pathspec>" better

^ permalink raw reply	[relevance 1%]

* [ANNOUNCE] Git v2.5.0-rc3
@ 2015-07-21 22:08  1% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-07-21 22:08 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

A release candidate Git v2.5.0-rc3 is now available for testing at
the usual places.  It is comprised of 579 non-merge commits since
v2.4.0, contributed by 70 people, 21 of which are new faces.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/testing/

The following public repositories all have a copy of the
'v2.5.0-rc3' tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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

New contributors whose contributions weren't in v2.4.0 are as follows.
Welcome to the Git development community!

  Allen Hubbe, Ariel Faigon, Blair Holloway, Christian Neukirchen,
  Danny Lin, Enrique Tobis, Frans Klaver, Fredrik Medley, Joe
  Cridge, Lars Kellogg-Stedman, Lawrence Siebert, Lex Spoon, Luke
  Mewburn, Miguel Torroja, Mike Edgar, Ossi Herrala, Panagiotis
  Astithas, Quentin Neill, Remi Lespinet, Sébastien Guimmara,
  and Thomas Schneider.

Returning contributors who helped this release are as follows.
Thanks for your continued support.

  Alexander Shopov, Alex Henrie, brian m. carlson, Carlos Martín
  Nieto, Charles Bailey, Clemens Buchacher, David Aguilar,
  David Turner, Dennis Kaarsemaker, Dimitriy Ryazantcev, Elia
  Pinto, Eric Sunshine, Fredrik Gustafsson, Jean-Noel Avila, Jeff
  King, Jiang Xin, Jim Hill, Johannes Schindelin, Johannes Sixt,
  Jonathan Nieder, Junio C Hamano, Karsten Blees, Karthik Nayak,
  Luke Diamand, Matthieu Moy, Max Kirillov, Michael Coleman,
  Michael Haggerty, Michael J Gruber, Mike Hommey, Nguyễn
  Thái Ngọc Duy, Patrick Steinhardt, Paul Tan, Peter Krefting,
  Phil Hord, Phillip Sz, Ralf Thielow, Ramsay Allan Jones, René
  Scharfe, Richard Hansen, Sebastian Schuberth, Stefan Beller,
  SZEDER Gábor, Thomas Braun, Thomas Gummerer, Tony Finch,
  Torsten Bögershausen, Trần Ngọc Quân, and Vitor Antunes.

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

Git 2.5 Release Notes (draft)
=============================

Updates since v2.4
------------------

UI, Workflows & Features

 * The bash completion script (in contrib/) learned a few options that
   "git revert" takes.

 * Whitespace breakages in deleted and context lines can also be
   painted in the output of "git diff" and friends with the new
   --ws-error-highlight option.

 * List of commands shown by "git help" are grouped along the workflow
   elements to help early learners.

 * "git p4" now detects the filetype (e.g. binary) correctly even when
   the files are opened exclusively.

 * git p4 attempts to better handle branches in Perforce.

 * "git p4" learned "--changes-block-size <n>" to read the changes in
   chunks from Perforce, instead of making one call to "p4 changes"
   that may trigger "too many rows scanned" error from Perforce.

 * More workaround for Perforce's row number limit in "git p4".

 * Unlike "$EDITOR" and "$GIT_EDITOR" that can hold the path to the
   command and initial options (e.g. "/path/to/emacs -nw"), 'git p4'
   did not let the shell interpolate the contents of the environment
   variable that name the editor "$P4EDITOR" (and "$EDITOR", too).
   This release makes it in line with the rest of Git, as well as with
   Perforce.

 * A new short-hand <branch>@{push} denotes the remote-tracking branch
   that tracks the branch at the remote the <branch> would be pushed
   to.

 * "git show-branch --topics HEAD" (with no other arguments) did not
   do anything interesting.  Instead, contrast the given revision
   against all the local branches by default.

 * A replacement for contrib/workdir/git-new-workdir that does not
   rely on symbolic links and make sharing of objects and refs safer
   by making the borrowee and borrowers aware of each other.

   Consider this as still an experimental feature; its UI is still
   likely to change.

 * Tweak the sample "store" backend of the credential helper to honor
   XDG configuration file locations when specified.

 * A heuristic we use to catch mistyped paths on the command line
   "git <cmd> <revs> <pathspec>" is to make sure that all the non-rev
   parameters in the later part of the command line are names of the
   files in the working tree, but that means "git grep $str -- \*.c"
   must always be disambiguated with "--", because nobody sane will
   create a file whose name literally is asterisk-dot-see.  Loosen the
   heuristic to declare that with a wildcard string the user likely
   meant to give us a pathspec.

 * "git merge FETCH_HEAD" learned that the previous "git fetch" could
   be to create an Octopus merge, i.e. recording multiple branches
   that are not marked as "not-for-merge"; this allows us to lose an
   old style invocation "git merge <msg> HEAD $commits..." in the
   implementation of "git pull" script; the old style syntax can now
   be deprecated (but not removed yet).

 * Filter scripts were run with SIGPIPE disabled on the Git side,
   expecting that they may not read what Git feeds them to filter.
   We however treated a filter that does not read its input fully
   before exiting as an error.  We no longer do and ignore EPIPE
   when writing to feed the filter scripts.

   This changes semantics, but arguably in a good way.  If a filter
   can produce its output without fully consuming its input using
   whatever magic, we now let it do so, instead of diagnosing it
   as a programming error.

 * Instead of dying immediately upon failing to obtain a lock, the
   locking (of refs etc) retries after a short while with backoff.

 * Introduce http.<url>.SSLCipherList configuration variable to tweak
   the list of cipher suite to be used with libcURL when talking with
   https:// sites.

 * "git subtree" script (in contrib/) used "echo -n" to produce
   progress messages in a non-portable way.

 * "git subtree" script (in contrib/) does not have --squash option
   when pushing, but the documentation and help text pretended as if
   it did.

 * The Git subcommand completion (in contrib/) no longer lists credential
   helpers among candidates; they are not something the end user would
   invoke interactively.

 * The index file can be taught with "update-index --untracked-cache"
   to optionally remember already seen untracked files, in order to
   speed up "git status" in a working tree with tons of cruft.

 * "git mergetool" learned to drive WinMerge as a backend.

 * "git upload-pack" that serves "git fetch" can be told to serve
   commits that are not at the tip of any ref, as long as they are
   reachable from a ref, with uploadpack.allowReachableSHA1InWant
   configuration variable.

 * "git cat-file --batch(-check)" learned the "--follow-symlinks"
   option that follows an in-tree symbolic link when asked about an
   object via extended SHA-1 syntax, e.g. HEAD:RelNotes that points at
   Documentation/RelNotes/2.5.0.txt.  With the new option, the command
   behaves as if HEAD:Documentation/RelNotes/2.5.0.txt was given as
   input instead.

   Consider this as still an experimental and incomplete feature:

    - We may want to do the same for in-index objects, e.g.
      asking for :RelNotes with this option should give
      :Documentation/RelNotes/2.5.0.txt, too

    - "git cat-file --follow-symlinks blob HEAD:RelNotes"
      may also be something we want to allow in the future.

 * "git send-email" learned the alias file format used by the sendmail
   program (in a simplified form; we obviously do not feed pipes).

 * "git am" learned am.threeWay configuration variable.

 * Traditionally, external low-level 3-way merge drivers are expected
   to produce their results based solely on the contents of the three
   variants given in temporary files named by %O, %A and %B on their
   command line.  Additionally allow them to look at the final path
   (given by %P).

 * "git blame" learned blame.showEmail configuration variable.

 * "git apply" cannot diagnose a patch corruption when the breakage is
   to mark the length of the hunk shorter than it really is on the
   hunk header line "@@ -l,k +m,n @@"; one special case it could is
   when the hunk becomes no-op (e.g. k == n == 2 for two-line context
   patch output), and it learned to do so in this special case.

 * Add the "--allow-unknown-type" option to "cat-file" to allow
   inspecting loose objects of an experimental or a broken type.

 * Many long-running operations show progress eye-candy, even when
   they are later backgrounded.  Hide the eye-candy when the process
   is sent to the background instead.
   (merge a4fb76c lm/squelch-bg-progress later to maint).


Performance, Internal Implementation, Development Support etc.

 * "unsigned char [20]" used throughout the code to represent object
   names are being converted into a semi-opaque "struct object_id".
   This effort is expected to interfere with other topics in flight,
   but hopefully will give us one extra level of abstraction in the
   end, when completed.

 * for_each_ref() callback functions were taught to name the objects
   not with "unsigned char sha1[20]" but with "struct object_id".

 * Catch a programmer mistake to feed a pointer not an array to
   ARRAY_SIZE() macro, by using a couple of GCC extensions.

 * Some error messages in "git config" were emitted without calling
   the usual error() facility.

 * When "add--interactive" splits a hunk into two overlapping hunks
   and then let the user choose only one, it sometimes feeds an
   incorrect patch text to "git apply".  Add tests to demonstrate
   this.

   I have a slight suspicion that this may be $gmane/87202 coming back
   and biting us (I seem to have said "let's run with this and see
   what happens" back then).

 * More line-ending tests.

 * An earlier rewrite to use strbuf_getwholeline() instead of fgets(3)
   to read packed-refs file revealed that the former is unacceptably
   inefficient.  It has been optimized by using getdelim(3) when
   available.

 * The refs API uses ref_lock struct which had its own "int fd", even
   though the same file descriptor was in the lock struct it contains.
   Clean-up the code to lose this redundant field.

 * There was a dead code that used to handle "git pull --tags" and
   show special-cased error message, which was made irrelevant when
   the semantics of the option changed back in Git 1.9 days.
   (merge 19d122b pt/pull-tags-error-diag later to maint).

 * Help us to find broken test script that splits the body part of the
   test by mistaken use of wrong kind of quotes.
   (merge d93d5d5 jc/test-prereq-validate later to maint).

 * Developer support to automatically detect broken &&-chain in the
   test scripts is now turned on by default.
   (merge 92b269f jk/test-chain-lint later to maint).

 * Error reporting mechanism used in "refs" API has been made more
   consistent.

 * "git pull" has more test coverage now.

 * "git pull" has become more aware of the options meant for
   underlying "git fetch" and then learned to use parse-options
   parser.

 * Clarify in the Makefile a guideline to decide use of USE_NSEC.

Also contains various documentation updates and code clean-ups.


Fixes since v2.4
----------------

Unless otherwise noted, all the fixes since v2.4 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * Git 2.4 broke setting verbosity and progress levels on "git clone"
   with native transports.
   (merge 822f0c4 mh/clone-verbosity-fix later to maint).

 * "git add -e" did not allow the user to abort the operation by
   killing the editor.
   (merge cb64800 jk/add-e-kill-editor later to maint).

 * Memory usage of "git index-pack" has been trimmed by tens of
   per-cent.
   (merge f0e7f11 nd/slim-index-pack-memory-usage later to maint).

 * "git rev-list --objects $old --not --all" to see if everything that
   is reachable from $old is already connected to the existing refs
   was very inefficient.
   (merge b6e8a3b jk/still-interesting later to maint).

 * "hash-object --literally" introduced in v2.2 was not prepared to
   take a really long object type name.
   (merge 1427a7f jc/hash-object later to maint).

 * "git rebase --quiet" was not quite quiet when there is nothing to
   do.
   (merge 22946a9 jk/rebase-quiet-noop later to maint).

 * The completion for "log --decorate=" parameter value was incorrect.
   (merge af16bda sg/complete-decorate-full-not-long later to maint).

 * "filter-branch" corrupted commit log message that ends with an
   incomplete line on platforms with some "sed" implementations that
   munge such a line.  Work it around by avoiding to use "sed".
   (merge df06201 jk/filter-branch-use-of-sed-on-incomplete-line later to maint).

 * "git daemon" fails to build from the source under NO_IPV6
   configuration (regression in 2.4).
   (merge d358f77 jc/daemon-no-ipv6-for-2.4.1 later to maint).

 * Some time ago, "git blame" (incorrectly) lost the convert_to_git()
   call when synthesizing a fake "tip" commit that represents the
   state in the working tree, which broke folks who record the history
   with LF line ending to make their project portable across platforms
   while terminating lines in their working tree files with CRLF for
   their platform.
   (merge 4bf256d tb/blame-resurrect-convert-to-git later to maint).

 * We avoid setting core.worktree when the repository location is the
   ".git" directory directly at the top level of the working tree, but
   the code misdetected the case in which the working tree is at the
   root level of the filesystem (which arguably is a silly thing to
   do, but still valid).
   (merge 84ccad8 jk/init-core-worktree-at-root later to maint).

 * "git commit --date=now" or anything that relies on approxidate lost
   the daylight-saving-time offset.
   (merge f6e6362 jc/epochtime-wo-tz later to maint).

 * Access to objects in repositories that borrow from another one on a
   slow NFS server unnecessarily got more expensive due to recent code
   becoming more cautious in a naive way not to lose objects to pruning.
   (merge ee1c6c3 jk/prune-mtime later to maint).

 * The codepaths that read .gitignore and .gitattributes files have been
   taught that these files encoded in UTF-8 may have UTF-8 BOM marker at
   the beginning; this makes it in line with what we do for configuration
   files already.
   (merge 27547e5 cn/bom-in-gitignore later to maint).

 * a few helper scripts in the test suite did not report errors
   correctly.
   (merge de248e9 ep/fix-test-lib-functions-report later to maint).

 * The default $HOME/.gitconfig file created upon "git config --global"
   that edits it had incorrectly spelled user.name and user.email
   entries in it.
   (merge 7e11052 oh/fix-config-default-user-name-section later to maint).

 * "git cat-file bl $blob" failed to barf even though there is no
   object type that is "bl".
   (merge b7994af jk/type-from-string-gently later to maint).

 * The usual "git diff" when seeing a file turning into a directory
   showed a patchset to remove the file and create all files in the
   directory, but "git diff --no-index" simply refused to work.  Also,
   when asked to compare a file and a directory, imitate POSIX "diff"
   and compare the file with the file with the same name in the
   directory, instead of refusing to run.
   (merge 0615173 jc/diff-no-index-d-f later to maint).

 * "git rebase -i" moved the "current" command from "todo" to "done" a
   bit too prematurely, losing a step when a "pick" did not even start.
   (merge 8cbc57c ph/rebase-i-redo later to maint).

 * The connection initiation code for "ssh" transport tried to absorb
   differences between the stock "ssh" and Putty-supplied "plink" and
   its derivatives, but the logic to tell that we are using "plink"
   variants were too loose and falsely triggered when "plink" appeared
   anywhere in the path (e.g. "/home/me/bin/uplink/ssh").
   (merge baaf233 bc/connect-plink later to maint).

 * We have prepended $GIT_EXEC_PATH and the path "git" is installed in
   (typically "/usr/bin") to $PATH when invoking subprograms and hooks
   for almost eternity, but the original use case the latter tried to
   support was semi-bogus (i.e. install git to /opt/foo/git and run it
   without having /opt/foo on $PATH), and more importantly it has
   become less and less relevant as Git grew more mainstream (i.e. the
   users would _want_ to have it on their $PATH).  Stop prepending the
   path in which "git" is installed to users' $PATH, as that would
   interfere the command search order people depend on (e.g. they may
   not like versions of programs that are unrelated to Git in /usr/bin
   and want to override them by having different ones in /usr/local/bin
   and have the latter directory earlier in their $PATH).
   (merge a0b4507 jk/git-no-more-argv0-path-munging later to maint).

 * core.excludesfile (defaulting to $XDG_HOME/git/ignore) is supposed
   to be overridden by repository-specific .git/info/exclude file, but
   the order was swapped from the beginning. This belatedly fixes it.
   (merge 099d2d8 jc/gitignore-precedence later to maint).

 * There was a commented-out (instead of being marked to expect
   failure) test that documented a breakage that was fixed since the
   test was written; turn it into a proper test.
   (merge 66d2e04 sb/t1020-cleanup later to maint).

 * The "log --decorate" enhancement in Git 2.4 that shows the commit
   at the tip of the current branch e.g. "HEAD -> master", did not
   work with --decorate=full.
   (merge 429ad20 mg/log-decorate-HEAD later to maint).

 * The ref API did not handle cases where 'refs/heads/xyzzy/frotz' is
   removed at the same time as 'refs/heads/xyzzy' is added (or vice
   versa) very well.
   (merge c628edf mh/ref-directory-file later to maint).

 * Multi-ref transaction support we merged a few releases ago
   unnecessarily kept many file descriptors open, risking to fail with
   resource exhaustion.  This is for 2.4.x track.
   (merge 185ce3a mh/write-refs-sooner-2.4 later to maint).

 * "git bundle verify" did not diagnose extra parameters on the
   command line.
   (merge 7886cfa ps/bundle-verify-arg later to maint).

 * Various documentation mark-up fixes to make the output more
   consistent in general and also make AsciiDoctor (an alternative
   formatter) happier.
   (merge d0258b9 jk/asciidoc-markup-fix later to maint).
   (merge ad3967a jk/stripspace-asciidoctor-fix later to maint).
   (merge 975e382 ja/tutorial-asciidoctor-fix later to maint).

 * The code to read pack-bitmap wanted to allocate a few hundred
   pointers to a structure, but by mistake allocated and leaked memory
   enough to hold that many actual structures.  Correct the allocation
   size and also have it on stack, as it is small enough.
   (merge 599dc76 rs/plug-leak-in-pack-bitmaps later to maint).

 * The pull.ff configuration was supposed to override the merge.ff
   configuration, but it didn't.
   (merge db9bb28 pt/pull-ff-vs-merge-ff later to maint).

 * "git pull --log" and "git pull --no-log" worked as expected, but
   "git pull --log=20" did not.
   (merge 5061a44 pt/pull-log-n later to maint).

 * "git rerere forget" in a repository without rerere enabled gave a
   cryptic error message; it should be a silent no-op instead.
   (merge 0544574 jk/rerere-forget-check-enabled later to maint).

 * "git rebase -i" fired post-rewrite hook when it shouldn't (namely,
   when it was told to stop sequencing with 'exec' insn).
   (merge 141ff8f mm/rebase-i-post-rewrite-exec later to maint).

 * Clarify that "log --raw" and "log --format=raw" are unrelated
   concepts.
   (merge 92de921 mm/log-format-raw-doc later to maint).

 * Make "git stash something --help" error out, so that users can
   safely say "git stash drop --help".
   (merge 5ba2831 jk/stash-options later to maint).

 * The clean/smudge interface did not work well when filtering an
   empty contents (failed and then passed the empty input through).
   It can be argued that a filter that produces anything but empty for
   an empty input is nonsense, but if the user wants to do strange
   things, then why not?
   (merge f6a1e1e jh/filter-empty-contents later to maint).

 * Communication between the HTTP server and http_backend process can
   lead to a dead-lock when relaying a large ref negotiation request.
   Diagnose the situation better, and mitigate it by reading such a
   request first into core (to a reasonable limit).
   (merge 636614f jk/http-backend-deadlock later to maint).

 * "git clean pathspec..." tried to lstat(2) and complain even for
   paths outside the given pathspec.
   (merge 838d6a9 dt/clean-pathspec-filter-then-lstat later to maint).

 * Recent "git prune" traverses young unreachable objects to safekeep
   old objects in the reachability chain from them, which sometimes
   caused error messages that are unnecessarily alarming.
   (merge ce4e7b2 jk/squelch-missing-link-warning-for-unreachable later to maint).

 * The configuration reader/writer uses mmap(2) interface to access
   the files; when we find a directory, it barfed with "Out of memory?".
   (merge 9ca0aaf jk/diagnose-config-mmap-failure later to maint).

 * "color.diff.plain" was a misnomer; give it 'color.diff.context' as
   a more logical synonym.
   (merge 8dbf3eb jk/color-diff-plain-is-context later to maint).

 * The setup code used to die when core.bare and core.worktree are set
   inconsistently, even for commands that do not need working tree.
   (merge fada767 jk/die-on-bogus-worktree-late later to maint).

 * Recent Mac OS X updates breaks the logic to detect that the machine
   is on the AC power in the sample pre-auto-gc script.
   (merge c54c7b3 pa/auto-gc-mac-osx later to maint).

 * "git commit --cleanup=scissors" was not careful enough to protect
   against getting fooled by a line that looked like scissors.
   (merge fbfa097 sg/commit-cleanup-scissors later to maint).

 * "Have we lost a race with competing repack?" check was too
   expensive, especially while receiving a huge object transfer
   that runs index-pack (e.g. "clone" or "fetch").
   (merge 0eeb077 jk/index-pack-reduce-recheck later to maint).

 * The tcsh completion writes a bash scriptlet but that would have
   failed for users with noclobber set.
   (merge 0b1f688 af/tcsh-completion-noclobber later to maint).

 * "git for-each-ref" reported "missing object" for 0{40} when it
   encounters a broken ref.  The lack of object whose name is 0{40} is
   not the problem; the ref being broken is.
   (merge 501cf47 mh/reporting-broken-refs-from-for-each-ref later to maint).

 * Various fixes around "git am" that applies a patch to a history
   that is not there yet.
   (merge 6ea3b67 pt/am-abort-fix later to maint).

 * "git fsck" used to ignore missing or invalid objects recorded in reflog.
   (merge 19bf6c9 mh/fsck-reflog-entries later to maint).

 * "git format-patch --ignore-if-upstream A..B" did not like to be fed
   tags as boundary commits.
   (merge 9b7a61d jc/do-not-feed-tags-to-clear-commit-marks later to maint).

 * "git fetch --depth=<depth>" and "git clone --depth=<depth>" issued
   a shallow transfer request even to an upload-pack that does not
   support the capability.
   (merge eb86a50 me/fetch-into-shallow-safety later to maint).

 * "git rebase" did not exit with failure when format-patch it invoked
   failed for whatever reason.
   (merge 60d708b cb/rebase-am-exit-code later to maint).

 * Fix a small bug in our use of umask() return value.
   (merge 3096b2e jk/fix-refresh-utime later to maint).

 * An ancient test framework enhancement to allow color was not
   entirely correct; this makes it work even when tput needs to read
   from the ~/.terminfo under the user's real HOME directory.
   (merge d5c1b7c rh/test-color-avoid-terminfo-in-original-home later to maint).

 * A minor bugfix when pack bitmap is used with "rev-list --count".
   (merge c8a70d3 jk/rev-list-no-bitmap-while-pruning later to maint).

 * "git config" failed to update the configuration file when the
   underlying filesystem is incapable of renaming a file that is still
   open.
   (merge 7a64592 kb/config-unmap-before-renaming later to maint).

 * Avoid possible ssize_t to int truncation.
   (merge 6c8afe4 mh/strbuf-read-file-returns-ssize-t later to maint).

 * When you say "!<ENTER>" while running say "git log", you'd confuse
   yourself in the resulting shell, that may look as if you took
   control back to the original shell you spawned "git log" from but
   that isn't what is happening.  To that new shell, we leaked
   GIT_PAGER_IN_USE environment variable that was meant as a local
   communication between the original "Git" and subprocesses that was
   spawned by it after we launched the pager, which caused many
   "interesting" things to happen, e.g. "git diff | cat" still paints
   its output in color by default.

   Stop leaking that environment variable to the pager's half of the
   fork; we only need it on "Git" side when we spawn the pager.
   (merge 124b519 jc/unexport-git-pager-in-use-in-pager later to maint).

 * Abandoning an already applied change in "git rebase -i" with
   "--continue" left CHERRY_PICK_HEAD and confused later steps.
   (merge 0e0aff4 js/rebase-i-clean-up-upon-continue-to-skip later to maint).

 * We used to ask libCURL to use the most secure authentication method
   available when talking to an HTTP proxy only when we were told to
   talk to one via configuration variables.  We now ask libCURL to
   always use the most secure authentication method, because the user
   can tell libCURL to use an HTTP proxy via an environment variable
   without using configuration variables.
   (merge 5841520 et/http-proxyauth later to maint).

 * A fix to a minor regression to "git fsck" in v2.2 era that started
   complaining about a body-less tag object when it lacks a separator
   empty line after its header to separate it with a non-existent body.
   (merge 84d18c0 jc/fsck-retire-require-eoh later to maint).

 * Code cleanups and documentation updates.
   (merge 0269f96 mm/usage-log-l-can-take-regex later to maint).
   (merge 64f2589 nd/t1509-chroot-test later to maint).
   (merge d201a1e sb/test-bitmap-free-at-end later to maint).
   (merge 05bfc7d sb/line-log-plug-pairdiff-leak later to maint).
   (merge 846e5df pt/xdg-config-path later to maint).
   (merge 1154aa4 jc/plug-fmt-merge-msg-leak later to maint).
   (merge 319b678 jk/sha1-file-reduce-useless-warnings later to maint).
   (merge 9a35c14 fg/document-commit-message-stripping later to maint).
   (merge bbf431c ps/doc-packfile-vs-pack-file later to maint).
   (merge 309a9e3 jk/skip-http-tests-under-no-curl later to maint).
   (merge ccd593c dl/branch-error-message later to maint).
   (merge 22570b6 rs/janitorial later to maint).
   (merge 5c2a581 mc/commit-doc-grammofix later to maint).
   (merge ce41720 ah/usage-strings later to maint).
   (merge e6a268c sb/glossary-submodule later to maint).
   (merge ec48a76 sb/submodule-doc-intro later to maint).
   (merge 14f8b9b jk/clone-dissociate later to maint).
   (merge 055c7e9 sb/pack-protocol-mention-smart-http later to maint).
   (merge 7c37a5d jk/make-fix-dependencies later to maint).
   (merge fc0aa39 sg/merge-summary-config later to maint).
   (merge 329af6c pt/t0302-needs-sanity later to maint).
   (merge d614f07 fk/doc-format-patch-vn later to maint).
   (merge 72dbb36 sg/completion-commit-cleanup later to maint).
   (merge e654eb2 es/utf8-stupid-compiler-workaround later to maint).
   (merge 34b935c es/osx-header-pollutes-mask-macro later to maint).
   (merge ab7fade jc/prompt-document-ps1-state-separator later to maint).
   (merge 25f600e mm/describe-doc later to maint).
   (merge 83fe167 mm/branch-doc-updates later to maint).
   (merge 75d2e5a ls/hint-rev-list-count later to maint).
   (merge edc8f71 cb/subtree-tests-update later to maint).
   (merge 5330e6e sb/p5310-and-chain later to maint).
   (merge c4ac525 tb/checkout-doc later to maint).
   (merge e479c5f jk/pretty-encoding-doc later to maint).
   (merge 7e837c6 ss/clone-guess-dir-name-simplify later to maint).

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

Changes since v2.5.0-rc2 are as follows:

Alex Henrie (2):
      l10n: ca.po: update translation
      l10n: ca.po: update translation

Alexander Shopov (2):
      l10n: Updated Bulgarian translation of git (2355t,0f,0u)
      l10n: Updated Bulgarian translation of git (2359t,0f,0u)

Dimitriy Ryazantcev (1):
      l10n: ru.po: update Russian translation

Eric Sunshine (2):
      Documentation/git-worktree: fix stale "git checkout --to" references
      Documentation/git: fix stale "MULTIPLE CHECKOUT MODE" reference

Jean-Noel Avila (2):
      l10n: fr.po v2.5.0-rc0 (2355t)
      l10n: fr v2.5.0 round 2 (2359t)

Jiang Xin (4):
      l10n: git.pot: v2.5.0 round 1 (65 new, 15 removed)
      l10n: zh_CN: for git v2.5.0 l10n round 1
      l10n: git.pot: v2.5.0 round 2 (9 new, 5 removed)
      l10n: zh_CN: for git v2.5.0 l10n round 2

Junio C Hamano (3):
      Git 2.4.6
      worktree: caution that this is still experimental
      Git 2.5.0-rc3

Peter Krefting (2):
      l10n: sv.po: Update Swedish translation (2355t0f0u)
      l10n: sv.po: Update Swedish translation (2359t0f0u)

Ralf Thielow (4):
      l10n: de.po: fix translation of "head nodes"
      l10n: de.po: translate "index" as "Index"
      l10n: de.po: translate 65 new messages
      l10n: de.po: translate 9 new messages

René Scharfe (1):
      diff: parse ws-error-highlight option more strictly

Stefan Beller (1):
      revision.c: remove unneeded check for NULL

Tony Finch (1):
      gitweb: fix typo in man page

Trần Ngọc Quân (2):
      l10n: Updated Vietnamese translation (2355t)
      l10n: Updated Vietnamese translation (2359t)

^ permalink raw reply	[relevance 1%]

* [ANNOUNCE] Git v2.5.0
@ 2015-07-27 20:47  1% Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-07-27 20:47 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

The latest feature release Git v2.5.0 is now available at the
usual places.  It is comprised of 583 non-merge commits since
v2.4.0, contributed by 70 people, 21 of which are new faces.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/

The following public repositories all have a copy of the 'v2.5.0'
tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  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

New contributors whose contributions weren't in v2.4.0 are as follows.
Welcome to the Git development community!

  Allen Hubbe, Ariel Faigon, Blair Holloway, Christian Neukirchen,
  Danny Lin, Enrique Tobis, Frans Klaver, Fredrik Medley, Joe
  Cridge, Lars Kellogg-Stedman, Lawrence Siebert, Lex Spoon, Luke
  Mewburn, Miguel Torroja, Mike Edgar, Ossi Herrala, Panagiotis
  Astithas, Quentin Neill, Remi Lespinet, Sébastien Guimmara,
  and Thomas Schneider.

Returning contributors who helped this release are as follows.
Thanks for your continued support.

  Alexander Shopov, Alex Henrie, brian m. carlson, Carlos Martín
  Nieto, Charles Bailey, Clemens Buchacher, David Aguilar,
  David Turner, Dennis Kaarsemaker, Dimitriy Ryazantcev, Elia
  Pinto, Eric Sunshine, Fredrik Gustafsson, Jean-Noel Avila, Jeff
  King, Jiang Xin, Jim Hill, Johannes Schindelin, Johannes Sixt,
  Jonathan Nieder, Junio C Hamano, Karsten Blees, Karthik Nayak,
  Luke Diamand, Matthieu Moy, Max Kirillov, Michael Coleman,
  Michael Haggerty, Michael J Gruber, Mike Hommey, Nguyễn
  Thái Ngọc Duy, Patrick Steinhardt, Paul Tan, Peter Krefting,
  Phil Hord, Phillip Sz, Ralf Thielow, Ramsay Allan Jones, René
  Scharfe, Richard Hansen, Sebastian Schuberth, Stefan Beller,
  SZEDER Gábor, Thomas Braun, Thomas Gummerer, Tony Finch,
  Torsten Bögershausen, Trần Ngọc Quân, and Vitor Antunes.

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

Git 2.5 Release Notes
=====================

Updates since v2.4
------------------

UI, Workflows & Features

 * The bash completion script (in contrib/) learned a few options that
   "git revert" takes.

 * Whitespace breakages in deleted and context lines can also be
   painted in the output of "git diff" and friends with the new
   --ws-error-highlight option.

 * List of commands shown by "git help" are grouped along the workflow
   elements to help early learners.

 * "git p4" now detects the filetype (e.g. binary) correctly even when
   the files are opened exclusively.

 * git p4 attempts to better handle branches in Perforce.

 * "git p4" learned "--changes-block-size <n>" to read the changes in
   chunks from Perforce, instead of making one call to "p4 changes"
   that may trigger "too many rows scanned" error from Perforce.

 * More workaround for Perforce's row number limit in "git p4".

 * Unlike "$EDITOR" and "$GIT_EDITOR" that can hold the path to the
   command and initial options (e.g. "/path/to/emacs -nw"), 'git p4'
   did not let the shell interpolate the contents of the environment
   variable that name the editor "$P4EDITOR" (and "$EDITOR", too).
   This release makes it in line with the rest of Git, as well as with
   Perforce.

 * A new short-hand <branch>@{push} denotes the remote-tracking branch
   that tracks the branch at the remote the <branch> would be pushed
   to.

 * "git show-branch --topics HEAD" (with no other arguments) did not
   do anything interesting.  Instead, contrast the given revision
   against all the local branches by default.

 * A replacement for contrib/workdir/git-new-workdir that does not
   rely on symbolic links and make sharing of objects and refs safer
   by making the borrowee and borrowers aware of each other.

   Consider this as still an experimental feature; its UI is still
   likely to change.

 * Tweak the sample "store" backend of the credential helper to honor
   XDG configuration file locations when specified.

 * A heuristic we use to catch mistyped paths on the command line
   "git <cmd> <revs> <pathspec>" is to make sure that all the non-rev
   parameters in the later part of the command line are names of the
   files in the working tree, but that means "git grep $str -- \*.c"
   must always be disambiguated with "--", because nobody sane will
   create a file whose name literally is asterisk-dot-see.  Loosen the
   heuristic to declare that with a wildcard string the user likely
   meant to give us a pathspec.

 * "git merge FETCH_HEAD" learned that the previous "git fetch" could
   be to create an Octopus merge, i.e. recording multiple branches
   that are not marked as "not-for-merge"; this allows us to lose an
   old style invocation "git merge <msg> HEAD $commits..." in the
   implementation of "git pull" script; the old style syntax can now
   be deprecated (but not removed yet).

 * Filter scripts were run with SIGPIPE disabled on the Git side,
   expecting that they may not read what Git feeds them to filter.
   We however treated a filter that does not read its input fully
   before exiting as an error.  We no longer do and ignore EPIPE
   when writing to feed the filter scripts.

   This changes semantics, but arguably in a good way.  If a filter
   can produce its output without fully consuming its input using
   whatever magic, we now let it do so, instead of diagnosing it
   as a programming error.

 * Instead of dying immediately upon failing to obtain a lock, the
   locking (of refs etc) retries after a short while with backoff.

 * Introduce http.<url>.SSLCipherList configuration variable to tweak
   the list of cipher suite to be used with libcURL when talking with
   https:// sites.

 * "git subtree" script (in contrib/) used "echo -n" to produce
   progress messages in a non-portable way.

 * "git subtree" script (in contrib/) does not have --squash option
   when pushing, but the documentation and help text pretended as if
   it did.

 * The Git subcommand completion (in contrib/) no longer lists credential
   helpers among candidates; they are not something the end user would
   invoke interactively.

 * The index file can be taught with "update-index --untracked-cache"
   to optionally remember already seen untracked files, in order to
   speed up "git status" in a working tree with tons of cruft.

 * "git mergetool" learned to drive WinMerge as a backend.

 * "git upload-pack" that serves "git fetch" can be told to serve
   commits that are not at the tip of any ref, as long as they are
   reachable from a ref, with uploadpack.allowReachableSHA1InWant
   configuration variable.

 * "git cat-file --batch(-check)" learned the "--follow-symlinks"
   option that follows an in-tree symbolic link when asked about an
   object via extended SHA-1 syntax, e.g. HEAD:RelNotes that points at
   Documentation/RelNotes/2.5.0.txt.  With the new option, the command
   behaves as if HEAD:Documentation/RelNotes/2.5.0.txt was given as
   input instead.

   Consider this as still an experimental and incomplete feature:

    - We may want to do the same for in-index objects, e.g.
      asking for :RelNotes with this option should give
      :Documentation/RelNotes/2.5.0.txt, too

    - "git cat-file --follow-symlinks blob HEAD:RelNotes"
      may also be something we want to allow in the future.

 * "git send-email" learned the alias file format used by the sendmail
   program (in a simplified form; we obviously do not feed pipes).

 * Traditionally, external low-level 3-way merge drivers are expected
   to produce their results based solely on the contents of the three
   variants given in temporary files named by %O, %A and %B on their
   command line.  Additionally allow them to look at the final path
   (given by %P).

 * "git blame" learned blame.showEmail configuration variable.

 * "git apply" cannot diagnose a patch corruption when the breakage is
   to mark the length of the hunk shorter than it really is on the
   hunk header line "@@ -l,k +m,n @@"; one special case it could is
   when the hunk becomes no-op (e.g. k == n == 2 for two-line context
   patch output), and it learned to do so in this special case.

 * Add the "--allow-unknown-type" option to "cat-file" to allow
   inspecting loose objects of an experimental or a broken type.

 * Many long-running operations show progress eye-candy, even when
   they are later backgrounded.  Hide the eye-candy when the process
   is sent to the background instead.
   (merge a4fb76c lm/squelch-bg-progress later to maint).


Performance, Internal Implementation, Development Support etc.

 * "unsigned char [20]" used throughout the code to represent object
   names are being converted into a semi-opaque "struct object_id".
   This effort is expected to interfere with other topics in flight,
   but hopefully will give us one extra level of abstraction in the
   end, when completed.

 * for_each_ref() callback functions were taught to name the objects
   not with "unsigned char sha1[20]" but with "struct object_id".

 * Catch a programmer mistake to feed a pointer not an array to
   ARRAY_SIZE() macro, by using a couple of GCC extensions.

 * Some error messages in "git config" were emitted without calling
   the usual error() facility.

 * When "add--interactive" splits a hunk into two overlapping hunks
   and then let the user choose only one, it sometimes feeds an
   incorrect patch text to "git apply".  Add tests to demonstrate
   this.

   I have a slight suspicion that this may be $gmane/87202 coming back
   and biting us (I seem to have said "let's run with this and see
   what happens" back then).

 * More line-ending tests.

 * An earlier rewrite to use strbuf_getwholeline() instead of fgets(3)
   to read packed-refs file revealed that the former is unacceptably
   inefficient.  It has been optimized by using getdelim(3) when
   available.

 * The refs API uses ref_lock struct which had its own "int fd", even
   though the same file descriptor was in the lock struct it contains.
   Clean-up the code to lose this redundant field.

 * There was a dead code that used to handle "git pull --tags" and
   show special-cased error message, which was made irrelevant when
   the semantics of the option changed back in Git 1.9 days.
   (merge 19d122b pt/pull-tags-error-diag later to maint).

 * Help us to find broken test script that splits the body part of the
   test by mistaken use of wrong kind of quotes.
   (merge d93d5d5 jc/test-prereq-validate later to maint).

 * Developer support to automatically detect broken &&-chain in the
   test scripts is now turned on by default.
   (merge 92b269f jk/test-chain-lint later to maint).

 * Error reporting mechanism used in "refs" API has been made more
   consistent.

 * "git pull" has more test coverage now.

 * "git pull" has become more aware of the options meant for
   underlying "git fetch" and then learned to use parse-options
   parser.

 * Clarify in the Makefile a guideline to decide use of USE_NSEC.

Also contains various documentation updates and code clean-ups.


Fixes since v2.4
----------------

Unless otherwise noted, all the fixes since v2.4 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).

 * Git 2.4 broke setting verbosity and progress levels on "git clone"
   with native transports.
   (merge 822f0c4 mh/clone-verbosity-fix later to maint).

 * "git add -e" did not allow the user to abort the operation by
   killing the editor.
   (merge cb64800 jk/add-e-kill-editor later to maint).

 * Memory usage of "git index-pack" has been trimmed by tens of
   per-cent.
   (merge f0e7f11 nd/slim-index-pack-memory-usage later to maint).

 * "git rev-list --objects $old --not --all" to see if everything that
   is reachable from $old is already connected to the existing refs
   was very inefficient.
   (merge b6e8a3b jk/still-interesting later to maint).

 * "hash-object --literally" introduced in v2.2 was not prepared to
   take a really long object type name.
   (merge 1427a7f jc/hash-object later to maint).

 * "git rebase --quiet" was not quite quiet when there is nothing to
   do.
   (merge 22946a9 jk/rebase-quiet-noop later to maint).

 * The completion for "log --decorate=" parameter value was incorrect.
   (merge af16bda sg/complete-decorate-full-not-long later to maint).

 * "filter-branch" corrupted commit log message that ends with an
   incomplete line on platforms with some "sed" implementations that
   munge such a line.  Work it around by avoiding to use "sed".
   (merge df06201 jk/filter-branch-use-of-sed-on-incomplete-line later to maint).

 * "git daemon" fails to build from the source under NO_IPV6
   configuration (regression in 2.4).
   (merge d358f77 jc/daemon-no-ipv6-for-2.4.1 later to maint).

 * Some time ago, "git blame" (incorrectly) lost the convert_to_git()
   call when synthesizing a fake "tip" commit that represents the
   state in the working tree, which broke folks who record the history
   with LF line ending to make their project portable across platforms
   while terminating lines in their working tree files with CRLF for
   their platform.
   (merge 4bf256d tb/blame-resurrect-convert-to-git later to maint).

 * We avoid setting core.worktree when the repository location is the
   ".git" directory directly at the top level of the working tree, but
   the code misdetected the case in which the working tree is at the
   root level of the filesystem (which arguably is a silly thing to
   do, but still valid).
   (merge 84ccad8 jk/init-core-worktree-at-root later to maint).

 * "git commit --date=now" or anything that relies on approxidate lost
   the daylight-saving-time offset.
   (merge f6e6362 jc/epochtime-wo-tz later to maint).

 * Access to objects in repositories that borrow from another one on a
   slow NFS server unnecessarily got more expensive due to recent code
   becoming more cautious in a naive way not to lose objects to pruning.
   (merge ee1c6c3 jk/prune-mtime later to maint).

 * The codepaths that read .gitignore and .gitattributes files have been
   taught that these files encoded in UTF-8 may have UTF-8 BOM marker at
   the beginning; this makes it in line with what we do for configuration
   files already.
   (merge 27547e5 cn/bom-in-gitignore later to maint).

 * a few helper scripts in the test suite did not report errors
   correctly.
   (merge de248e9 ep/fix-test-lib-functions-report later to maint).

 * The default $HOME/.gitconfig file created upon "git config --global"
   that edits it had incorrectly spelled user.name and user.email
   entries in it.
   (merge 7e11052 oh/fix-config-default-user-name-section later to maint).

 * "git cat-file bl $blob" failed to barf even though there is no
   object type that is "bl".
   (merge b7994af jk/type-from-string-gently later to maint).

 * The usual "git diff" when seeing a file turning into a directory
   showed a patchset to remove the file and create all files in the
   directory, but "git diff --no-index" simply refused to work.  Also,
   when asked to compare a file and a directory, imitate POSIX "diff"
   and compare the file with the file with the same name in the
   directory, instead of refusing to run.
   (merge 0615173 jc/diff-no-index-d-f later to maint).

 * "git rebase -i" moved the "current" command from "todo" to "done" a
   bit too prematurely, losing a step when a "pick" did not even start.
   (merge 8cbc57c ph/rebase-i-redo later to maint).

 * The connection initiation code for "ssh" transport tried to absorb
   differences between the stock "ssh" and Putty-supplied "plink" and
   its derivatives, but the logic to tell that we are using "plink"
   variants were too loose and falsely triggered when "plink" appeared
   anywhere in the path (e.g. "/home/me/bin/uplink/ssh").
   (merge baaf233 bc/connect-plink later to maint).

 * We have prepended $GIT_EXEC_PATH and the path "git" is installed in
   (typically "/usr/bin") to $PATH when invoking subprograms and hooks
   for almost eternity, but the original use case the latter tried to
   support was semi-bogus (i.e. install git to /opt/foo/git and run it
   without having /opt/foo on $PATH), and more importantly it has
   become less and less relevant as Git grew more mainstream (i.e. the
   users would _want_ to have it on their $PATH).  Stop prepending the
   path in which "git" is installed to users' $PATH, as that would
   interfere the command search order people depend on (e.g. they may
   not like versions of programs that are unrelated to Git in /usr/bin
   and want to override them by having different ones in /usr/local/bin
   and have the latter directory earlier in their $PATH).
   (merge a0b4507 jk/git-no-more-argv0-path-munging later to maint).

 * core.excludesfile (defaulting to $XDG_HOME/git/ignore) is supposed
   to be overridden by repository-specific .git/info/exclude file, but
   the order was swapped from the beginning. This belatedly fixes it.
   (merge 099d2d8 jc/gitignore-precedence later to maint).

 * There was a commented-out (instead of being marked to expect
   failure) test that documented a breakage that was fixed since the
   test was written; turn it into a proper test.
   (merge 66d2e04 sb/t1020-cleanup later to maint).

 * The "log --decorate" enhancement in Git 2.4 that shows the commit
   at the tip of the current branch e.g. "HEAD -> master", did not
   work with --decorate=full.
   (merge 429ad20 mg/log-decorate-HEAD later to maint).

 * The ref API did not handle cases where 'refs/heads/xyzzy/frotz' is
   removed at the same time as 'refs/heads/xyzzy' is added (or vice
   versa) very well.
   (merge c628edf mh/ref-directory-file later to maint).

 * Multi-ref transaction support we merged a few releases ago
   unnecessarily kept many file descriptors open, risking to fail with
   resource exhaustion.  This is for 2.4.x track.
   (merge 185ce3a mh/write-refs-sooner-2.4 later to maint).

 * "git bundle verify" did not diagnose extra parameters on the
   command line.
   (merge 7886cfa ps/bundle-verify-arg later to maint).

 * Various documentation mark-up fixes to make the output more
   consistent in general and also make AsciiDoctor (an alternative
   formatter) happier.
   (merge d0258b9 jk/asciidoc-markup-fix later to maint).
   (merge ad3967a jk/stripspace-asciidoctor-fix later to maint).
   (merge 975e382 ja/tutorial-asciidoctor-fix later to maint).

 * The code to read pack-bitmap wanted to allocate a few hundred
   pointers to a structure, but by mistake allocated and leaked memory
   enough to hold that many actual structures.  Correct the allocation
   size and also have it on stack, as it is small enough.
   (merge 599dc76 rs/plug-leak-in-pack-bitmaps later to maint).

 * The pull.ff configuration was supposed to override the merge.ff
   configuration, but it didn't.
   (merge db9bb28 pt/pull-ff-vs-merge-ff later to maint).

 * "git pull --log" and "git pull --no-log" worked as expected, but
   "git pull --log=20" did not.
   (merge 5061a44 pt/pull-log-n later to maint).

 * "git rerere forget" in a repository without rerere enabled gave a
   cryptic error message; it should be a silent no-op instead.
   (merge 0544574 jk/rerere-forget-check-enabled later to maint).

 * "git rebase -i" fired post-rewrite hook when it shouldn't (namely,
   when it was told to stop sequencing with 'exec' insn).
   (merge 141ff8f mm/rebase-i-post-rewrite-exec later to maint).

 * Clarify that "log --raw" and "log --format=raw" are unrelated
   concepts.
   (merge 92de921 mm/log-format-raw-doc later to maint).

 * Make "git stash something --help" error out, so that users can
   safely say "git stash drop --help".
   (merge 5ba2831 jk/stash-options later to maint).

 * The clean/smudge interface did not work well when filtering an
   empty contents (failed and then passed the empty input through).
   It can be argued that a filter that produces anything but empty for
   an empty input is nonsense, but if the user wants to do strange
   things, then why not?
   (merge f6a1e1e jh/filter-empty-contents later to maint).

 * Communication between the HTTP server and http_backend process can
   lead to a dead-lock when relaying a large ref negotiation request.
   Diagnose the situation better, and mitigate it by reading such a
   request first into core (to a reasonable limit).
   (merge 636614f jk/http-backend-deadlock later to maint).

 * "git clean pathspec..." tried to lstat(2) and complain even for
   paths outside the given pathspec.
   (merge 838d6a9 dt/clean-pathspec-filter-then-lstat later to maint).

 * Recent "git prune" traverses young unreachable objects to safekeep
   old objects in the reachability chain from them, which sometimes
   caused error messages that are unnecessarily alarming.
   (merge ce4e7b2 jk/squelch-missing-link-warning-for-unreachable later to maint).

 * The configuration reader/writer uses mmap(2) interface to access
   the files; when we find a directory, it barfed with "Out of memory?".
   (merge 9ca0aaf jk/diagnose-config-mmap-failure later to maint).

 * "color.diff.plain" was a misnomer; give it 'color.diff.context' as
   a more logical synonym.
   (merge 8dbf3eb jk/color-diff-plain-is-context later to maint).

 * The setup code used to die when core.bare and core.worktree are set
   inconsistently, even for commands that do not need working tree.
   (merge fada767 jk/die-on-bogus-worktree-late later to maint).

 * Recent Mac OS X updates breaks the logic to detect that the machine
   is on the AC power in the sample pre-auto-gc script.
   (merge c54c7b3 pa/auto-gc-mac-osx later to maint).

 * "git commit --cleanup=scissors" was not careful enough to protect
   against getting fooled by a line that looked like scissors.
   (merge fbfa097 sg/commit-cleanup-scissors later to maint).

 * "Have we lost a race with competing repack?" check was too
   expensive, especially while receiving a huge object transfer
   that runs index-pack (e.g. "clone" or "fetch").
   (merge 0eeb077 jk/index-pack-reduce-recheck later to maint).

 * The tcsh completion writes a bash scriptlet but that would have
   failed for users with noclobber set.
   (merge 0b1f688 af/tcsh-completion-noclobber later to maint).

 * "git for-each-ref" reported "missing object" for 0{40} when it
   encounters a broken ref.  The lack of object whose name is 0{40} is
   not the problem; the ref being broken is.
   (merge 501cf47 mh/reporting-broken-refs-from-for-each-ref later to maint).

 * Various fixes around "git am" that applies a patch to a history
   that is not there yet.
   (merge 6ea3b67 pt/am-abort-fix later to maint).

 * "git fsck" used to ignore missing or invalid objects recorded in reflog.
   (merge 19bf6c9 mh/fsck-reflog-entries later to maint).

 * "git format-patch --ignore-if-upstream A..B" did not like to be fed
   tags as boundary commits.
   (merge 9b7a61d jc/do-not-feed-tags-to-clear-commit-marks later to maint).

 * "git fetch --depth=<depth>" and "git clone --depth=<depth>" issued
   a shallow transfer request even to an upload-pack that does not
   support the capability.
   (merge eb86a50 me/fetch-into-shallow-safety later to maint).

 * "git rebase" did not exit with failure when format-patch it invoked
   failed for whatever reason.
   (merge 60d708b cb/rebase-am-exit-code later to maint).

 * Fix a small bug in our use of umask() return value.
   (merge 3096b2e jk/fix-refresh-utime later to maint).

 * An ancient test framework enhancement to allow color was not
   entirely correct; this makes it work even when tput needs to read
   from the ~/.terminfo under the user's real HOME directory.
   (merge d5c1b7c rh/test-color-avoid-terminfo-in-original-home later to maint).

 * A minor bugfix when pack bitmap is used with "rev-list --count".
   (merge c8a70d3 jk/rev-list-no-bitmap-while-pruning later to maint).

 * "git config" failed to update the configuration file when the
   underlying filesystem is incapable of renaming a file that is still
   open.
   (merge 7a64592 kb/config-unmap-before-renaming later to maint).

 * Avoid possible ssize_t to int truncation.
   (merge 6c8afe4 mh/strbuf-read-file-returns-ssize-t later to maint).

 * When you say "!<ENTER>" while running say "git log", you'd confuse
   yourself in the resulting shell, that may look as if you took
   control back to the original shell you spawned "git log" from but
   that isn't what is happening.  To that new shell, we leaked
   GIT_PAGER_IN_USE environment variable that was meant as a local
   communication between the original "Git" and subprocesses that was
   spawned by it after we launched the pager, which caused many
   "interesting" things to happen, e.g. "git diff | cat" still paints
   its output in color by default.

   Stop leaking that environment variable to the pager's half of the
   fork; we only need it on "Git" side when we spawn the pager.
   (merge 124b519 jc/unexport-git-pager-in-use-in-pager later to maint).

 * Abandoning an already applied change in "git rebase -i" with
   "--continue" left CHERRY_PICK_HEAD and confused later steps.
   (merge 0e0aff4 js/rebase-i-clean-up-upon-continue-to-skip later to maint).

 * We used to ask libCURL to use the most secure authentication method
   available when talking to an HTTP proxy only when we were told to
   talk to one via configuration variables.  We now ask libCURL to
   always use the most secure authentication method, because the user
   can tell libCURL to use an HTTP proxy via an environment variable
   without using configuration variables.
   (merge 5841520 et/http-proxyauth later to maint).

 * A fix to a minor regression to "git fsck" in v2.2 era that started
   complaining about a body-less tag object when it lacks a separator
   empty line after its header to separate it with a non-existent body.
   (merge 84d18c0 jc/fsck-retire-require-eoh later to maint).

 * Code cleanups and documentation updates.
   (merge 0269f96 mm/usage-log-l-can-take-regex later to maint).
   (merge 64f2589 nd/t1509-chroot-test later to maint).
   (merge d201a1e sb/test-bitmap-free-at-end later to maint).
   (merge 05bfc7d sb/line-log-plug-pairdiff-leak later to maint).
   (merge 846e5df pt/xdg-config-path later to maint).
   (merge 1154aa4 jc/plug-fmt-merge-msg-leak later to maint).
   (merge 319b678 jk/sha1-file-reduce-useless-warnings later to maint).
   (merge 9a35c14 fg/document-commit-message-stripping later to maint).
   (merge bbf431c ps/doc-packfile-vs-pack-file later to maint).
   (merge 309a9e3 jk/skip-http-tests-under-no-curl later to maint).
   (merge ccd593c dl/branch-error-message later to maint).
   (merge 22570b6 rs/janitorial later to maint).
   (merge 5c2a581 mc/commit-doc-grammofix later to maint).
   (merge ce41720 ah/usage-strings later to maint).
   (merge e6a268c sb/glossary-submodule later to maint).
   (merge ec48a76 sb/submodule-doc-intro later to maint).
   (merge 14f8b9b jk/clone-dissociate later to maint).
   (merge 055c7e9 sb/pack-protocol-mention-smart-http later to maint).
   (merge 7c37a5d jk/make-fix-dependencies later to maint).
   (merge fc0aa39 sg/merge-summary-config later to maint).
   (merge 329af6c pt/t0302-needs-sanity later to maint).
   (merge d614f07 fk/doc-format-patch-vn later to maint).
   (merge 72dbb36 sg/completion-commit-cleanup later to maint).
   (merge e654eb2 es/utf8-stupid-compiler-workaround later to maint).
   (merge 34b935c es/osx-header-pollutes-mask-macro later to maint).
   (merge ab7fade jc/prompt-document-ps1-state-separator later to maint).
   (merge 25f600e mm/describe-doc later to maint).
   (merge 83fe167 mm/branch-doc-updates later to maint).
   (merge 75d2e5a ls/hint-rev-list-count later to maint).
   (merge edc8f71 cb/subtree-tests-update later to maint).
   (merge 5330e6e sb/p5310-and-chain later to maint).
   (merge c4ac525 tb/checkout-doc later to maint).
   (merge e479c5f jk/pretty-encoding-doc later to maint).
   (merge 7e837c6 ss/clone-guess-dir-name-simplify later to maint).

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

Changes since v2.4.0 are as follows:

Alex Henrie (3):
      blame, log: format usage strings similarly to those in documentation
      l10n: ca.po: update translation
      l10n: ca.po: update translation

Alexander Shopov (2):
      l10n: Updated Bulgarian translation of git (2355t,0f,0u)
      l10n: Updated Bulgarian translation of git (2359t,0f,0u)

Allen Hubbe (1):
      send-email: add sendmail email aliases format

Ariel Faigon (1):
      git-completion.tcsh: fix redirect with noclobber

Blair Holloway (1):
      git-p4: fix filetype detection on files opened exclusively

Carlos Martín Nieto (1):
      dir: allow a BOM at the beginning of exclude files

Charles Bailey (4):
      contrib/subtree: use tabs consitently for indentation in tests
      contrib/subtree: fix broken &&-chains and revealed test error
      contrib/subtree: small tidy-up to test
      Fix definition of ARRAY_SIZE for non-gcc builds

Christian Neukirchen (1):
      cvsimport: silence regex warning appearing in Perl 5.22.

Clemens Buchacher (1):
      rebase: return non-zero error code if format-patch fails

Danny Lin (3):
      branch: do not call a "remote-tracking branch" a "remote branch"
      contrib/subtree: there's no push --squash
      contrib/subtree: portability fix for string printing

David Aguilar (2):
      mergetool--lib: set IFS for difftool and mergetool
      mergetools: add winmerge as a builtin tool

David Turner (4):
      clean: only lstat files in pathspec
      tree-walk: learn get_tree_entry_follow_symlinks
      sha1_name: get_sha1_with_context learns to follow symlinks
      cat-file: add --follow-symlinks to --batch

Dennis Kaarsemaker (1):
      checkout: don't require a work tree when checking out into a new one

Dimitriy Ryazantcev (1):
      l10n: ru.po: update Russian translation

Elia Pinto (2):
      test-lib-functions.sh: fix the second argument to some helper functions
      git-compat-util.h: implement a different ARRAY_SIZE macro for for safely deriving the size of array

Enrique Tobis (1):
      http: always use any proxy auth method available

Eric Sunshine (44):
      git-hash-object.txt: document --literally option
      hash-object --literally: fix buffer overrun with extra-long object type
      t1007: add hash-object --literally tests
      command-list: prepare machinery for upcoming "common groups" section
      generate-cmdlist: parse common group commands
      send-email: further document missing sendmail aliases functionality
      send-email: visually distinguish sendmail aliases parser warnings
      send-email: drop noise comments which merely repeat what code says
      send-email: fix style: cuddle 'elsif' and 'else' with closing brace
      send-email: refactor sendmail aliases parser
      send-email: simplify sendmail aliases comment and blank line recognizer
      send-email: implement sendmail aliases line continuation support
      t9001: refactor sendmail aliases test infrastructure
      t9001: add sendmail aliases line continuation tests
      send-email: further warn about unsupported sendmail aliases features
      ewah/bitmap: silence warning about MASK macro redefinition
      config.mak.uname: Darwin: define HAVE_GETDELIM for modern OS X releases
      configure: add getdelim() check
      utf8: NO_ICONV: silence uninitialized variable warning
      Documentation/git-checkout: fix incorrect worktree prune command
      Documentation/git-worktree: associate options with commands
      Documentation: move linked worktree description from checkout to worktree
      Documentation/git-worktree: add BUGS section
      Documentation/git-worktree: split technical info from general description
      Documentation/git-worktree: add high-level 'lock' overview
      Documentation/git-worktree: add EXAMPLES section
      checkout: fix bug with --to and relative HEAD
      checkout: relocate --to's "no branch specified" check
      checkout: prepare_linked_checkout: drop now-unused 'new' argument
      checkout: make --to unconditionally verbose
      checkout: drop 'checkout_opts' dependency from prepare_linked_checkout
      worktree: introduce "add" command
      worktree: add --force option
      worktree: add --detach option
      worktree: add -b/-B options
      tests: worktree: retrofit "checkout --to" tests for "worktree add"
      checkout: retire --to option
      checkout: require worktree unconditionally
      worktree: extract basename computation to new function
      worktree: add: make -b/-B default to HEAD when <branch> is omitted
      worktree: add: auto-vivify new branch when <branch> is omitted
      checkout: retire --ignore-other-worktrees in favor of --force
      Documentation/git-worktree: fix stale "git checkout --to" references
      Documentation/git: fix stale "MULTIPLE CHECKOUT MODE" reference

Frans Klaver (1):
      doc: format-patch: fix typo

Fredrik Gustafsson (1):
      Documentation: clarify how "git commit" cleans up the edited log message

Fredrik Medley (3):
      config.txt: clarify allowTipSHA1InWant with camelCase
      upload-pack: prepare to extend allow-tip-sha1-in-want
      upload-pack: optionally allow fetching reachable sha1

Jean-Noel Avila (3):
      doc: fix unmatched code fences
      l10n: fr.po v2.5.0-rc0 (2355t)
      l10n: fr v2.5.0 round 2 (2359t)

Jeff King (83):
      sha1_file: squelch "packfile cannot be accessed" warnings
      init: don't set core.worktree when initializing /.git
      strbuf_getwholeline: use getc macro
      git-compat-util: add fallbacks for unlocked stdio
      strbuf_getwholeline: use getc_unlocked
      config: use getc_unlocked when reading from file
      strbuf_addch: avoid calling strbuf_grow
      strbuf_getwholeline: avoid calling strbuf_grow
      strbuf_getwholeline: use getdelim if it is available
      read_packed_refs: avoid double-checking sane refs
      t1430: add another refs-escape test
      type_from_string_gently: make sure length matches
      limit_list: avoid quadratic behavior from still_interesting
      reachable: only mark local objects as recent
      sha1_file: freshen pack objects before loose
      sha1_file: only freshen packs once per run
      t3903: stop hard-coding commit sha1s
      t3903: avoid applying onto dirty index
      stash: require a clean index to apply
      stop putting argv[0] dirname at front of PATH
      rebase: silence "git checkout" for noop rebase
      test-lib: turn on GIT_TEST_CHAIN_LINT by default
      filter-branch: avoid passing commit message through sed
      remote.c: drop default_remote_name variable
      t/lib-httpd.sh: skip tests if NO_CURL is defined
      add: check return value of launch_editor
      doc: fix unmatched code fences in git-stripspace
      doc: fix misrendering due to `single quote'
      doc: fix unquoted use of "{type}"
      doc: fix hanging "+"-continuation
      doc: fix length of underlined section-title
      doc/add: reformat `--edit` option
      doc: convert \--option to --option
      doc: drop backslash quoting of some curly braces
      doc: put example URLs and emails inside literal backticks
      doc: convert AsciiDoc {?foo} to ifdef::foo[]
      rerere: exit silently on "forget" when rerere is disabled
      http-backend: fix die recursion with custom handler
      progress: treat "no terminal" as being in the foreground
      t5551: factor out tag creation
      stash: complain about unknown flags
      stash: recognize "--help" for subcommands
      remote.c: refactor setup of branch->merge list
      remote.c: drop "remote" pointer from "struct branch"
      remote.c: hoist branch.*.remote lookup out of remote_get_1
      remote.c: provide per-branch pushremote name
      remote.c: hoist read_config into remote_get_1
      remote.c: introduce branch_get_upstream helper
      remote.c: report specific errors from branch_get_upstream
      test_bitmap_walk: free bitmap with bitmap_free
      remote.c: untangle error logic in branch_get_upstream
      remote.c: return upstream name from stat_tracking_info
      remote.c: add branch_get_push
      sha1_name: refactor upstream_mark
      sha1_name: refactor interpret_upstream_mark
      sha1_name: implement @{push} shorthand
      for-each-ref: use skip_prefix instead of starts_with
      for-each-ref: accept "%(push)" format
      http-backend: spool ref negotiation requests to buffer
      clone: use OPT_STRING_LIST for --reference
      clone: reorder --dissociate and --reference options
      t7063: hide stderr from setup inside prereq
      diff: accept color.diff.context as a synonym for "plain"
      diff.h: rename DIFF_PLAIN color slot to DIFF_CONTEXT
      read-cache.c: drop PROT_WRITE from mmap of index
      config.c: fix mmap leak when writing config
      config.c: avoid xmmap error messages
      config.c: rewrite ENODEV into EISDIR when mmap fails
      Makefile: drop dependency between git-instaweb and gitweb
      Makefile: avoid timestamp updates to GIT-BUILD-OPTIONS
      Makefile: silence perl/PM.stamp recipe
      setup_git_directory: delay core.bare/core.worktree errors
      add quieter versions of parse_{tree,commit}
      silence broken link warnings with revs->ignore_missing_links
      suppress errors on missing UNINTERESTING links
      ewah: use less generic macro name
      index-pack: fix truncation of off_t in comparison
      index-pack: avoid excessive re-reading of pack directory
      Revert "stash: require a clean index to apply"
      docs: clarify that --encoding can produce invalid sequences
      for_each_packed_object: automatically open pack index
      rev-list: disable --use-bitmap-index when pruning commits
      check_and_freshen_file: fix reversed success-check

Jiang Xin (4):
      l10n: git.pot: v2.5.0 round 1 (65 new, 15 removed)
      l10n: zh_CN: for git v2.5.0 l10n round 1
      l10n: git.pot: v2.5.0 round 2 (9 new, 5 removed)
      l10n: zh_CN: for git v2.5.0 l10n round 2

Jim Hill (1):
      sha1_file: pass empty buffer to index empty file

Joe Cridge (1):
      git-prompt.sh: document GIT_PS1_STATESEPARATOR

Johannes Schindelin (2):
      t3404: demonstrate CHERRY_PICK_HEAD bug
      rebase -i: do not leave a CHERRY_PICK_HEAD file behind

Johannes Sixt (5):
      compat/mingw: stubs for getpgid() and tcgetpgrp()
      lockfile: replace random() by rand()
      help.c: wrap wait-only poll() invocation in sleep_millisec()
      lockfile: convert retry timeout computations to millisecond
      lockfile: wait using sleep_millisec() instead of select()

Jonathan Nieder (1):
      config: use error() instead of fprintf(stderr, ...)

Junio C Hamano (77):
      t2026: fix broken &&-chain
      t0302: "unreadable" test needs POSIXPERM
      diff-no-index: DWIM "diff D F" into "diff D/F F"
      diff-no-index: align D/F handling with that of normal Git
      parse_date_basic(): return early when given a bogus timestamp
      parse_date_basic(): let the system handle DST conversion
      add_excludes_from_file: clarify the bom skipping logic
      utf8-bom: introduce skip_utf8_bom() helper
      config: use utf8_bom[] from utf.[ch] in git_parse_source()
      attr: skip UTF8 BOM at the beginning of the input file
      fmt-merge-msg: plug small leak of commit buffer
      ignore: info/exclude should trump core.excludesfile
      test: validate prerequistes syntax
      merge: test the top-level merge driver
      merge: simplify code flow
      t5520: style fixes
      t5520: test pulling an octopus into an unborn branch
      merge: clarify "pulling into void" special case
      merge: do not check argc to determine number of remote heads
      merge: small leakfix and code simplification
      merge: clarify collect_parents() logic
      merge: split reduce_parents() out of collect_parents()
      merge: narrow scope of merge_names
      merge: extract prepare_merge_message() logic out
      merge: make collect_parents() auto-generate the merge message
      merge: decide if we auto-generate the message early in collect_parents()
      merge: handle FETCH_HEAD internally
      merge: deprecate 'git merge <message> HEAD <commit>' syntax
      write_sha1_file(): do not use a separate sha1[] array
      daemon: unbreak NO_IPV6 build regression
      First batch for 2.5 cycle
      tests: skip dav http-push tests under NO_EXPAT=NoThanks
      Second batch for 2.5 cycle
      Git 2.3.8
      log: decorate HEAD with branch name under --decorate=full, too
      log: do not shorten decoration names too early
      Git 2.4.1
      Third batch for 2.5 cycle
      copy.c: make copy_fd() report its status silently
      filter_buffer_or_fd(): ignore EPIPE
      t5407: use <<- to align the expected output
      Fourth batch for 2.5 cycle
      t4015: modernise style
      t4015: separate common setup and per-test expectation
      Fifth batch for 2.5 cycle
      Git 2.4.2
      diff.c: add emit_del_line() and emit_context_line()
      diff.c: --ws-error-highlight=<kind> option
      t9001: write $HOME/, not ~/, to help shells without tilde expansion
      xmmap(): drop "Out of memory?"
      apply: reject a hunk that does not do anything
      Sixth batch for 2.5 cycle
      format-patch: do not feed tags to clear_commit_marks()
      ll-merge: pass the original path to external drivers
      The first half of the seventh batch for 2.5
      Git 2.4.3
      Second half of seventh batch
      Git 2.4.4
      Eighth batch for 2.5
      Revert "diff-lib.c: adjust position of i-t-a entries in diff"
      Ninth batch for 2.5
      Git 2.4.5
      Git 2.5.0-rc0
      fsck: it is OK for a tag and a commit to lack the body
      Git 2.5.0-rc1
      pager: do not leak "GIT_PAGER_IN_USE" to the pager
      index-pack: fix allocation of sorted_by_pos array
      The last minute bits of fixes
      Revert "checkout: retire --ignore-other-worktrees in favor of --force"
      Git 2.5.0-rc2
      Git 2.4.6
      worktree: caution that this is still experimental
      Git 2.5.0-rc3
      Revert "git-am: add am.threeWay config variable"
      RelNotes: am.threeWay does not exist (yet)
      Git 2.4.7
      Git 2.5

Karsten Blees (2):
      config.c: fix writing config files on Windows network shares
      Makefile / racy-git.txt: clarify USE_NSEC prerequisites

Karthik Nayak (4):
      sha1_file: support reading from a loose object of unknown type
      cat-file: make the options mutually exclusive
      cat-file: teach cat-file a '--allow-unknown-type' option
      t1006: add tests for git cat-file --allow-unknown-type

Lars Kellogg-Stedman (1):
      http: add support for specifying an SSL cipher list

Lawrence Siebert (1):
      rev-list: add --count to usage guide

Lex Spoon (1):
      git-p4: use -m when running p4 changes

Luke Diamand (11):
      git-p4: fix small bug in locked test scripts
      git-p4: small fix for locked-file-move-test
      git-p4: t9814: prevent --chain-lint failure
      git-p4: add failing tests for case-folding p4d
      git-p4: add failing test for P4EDITOR handling
      git-p4: fix handling of multi-word P4EDITOR
      git-p4: tests: use test-chmtime in place of touch
      git-p4: additional testing of --changes-block-size
      git-p4: test with limited p4 server results
      git-p4: add tests for non-numeric revision range
      git-p4: fixing --changes-block-size handling

Luke Mewburn (1):
      progress: no progress in background

Matthieu Moy (16):
      t3701-add-interactive: simplify code
      add -p: demonstrate failure when running 'edit' after a split
      t3904-stash-patch: fix test description
      t3904-stash-patch: factor PERL prereq at the top of the file
      stash -p: demonstrate failure of split with mixed y/n
      Documentation: change -L:<regex> to -L:<funcname>
      log -L: improve error message on malformed argument
      Documentation/log: clarify what --raw means
      Documentation/log: clarify sha1 non-abbreviation in log --raw
      rebase -i: demonstrate incorrect behavior of post-rewrite
      rebase -i: fix post-rewrite hook with failed exec command
      Documentation/describe: improve one-line summary
      git-multimail: update to release 1.1.0
      git-multimail: update to release 1.1.1
      Documentation/branch: document -d --force and -m --force
      Documentation/branch: document -M and -D in terms of --force

Max Kirillov (3):
      checkout: do not fail if target is an empty directory
      git-common-dir: make "modules/" per-working-directory directory
      prune --worktrees: fix expire vs worktree existence condition

Michael Coleman (1):
      Documentation/git-commit: grammofix

Michael Haggerty (99):
      t1404: new tests of ref D/F conflicts within transactions
      is_refname_available(): revamp the comments
      is_refname_available(): avoid shadowing "dir" variable
      is_refname_available(): convert local variable "dirname" to strbuf
      entry_matches(): inline function
      report_refname_conflict(): inline function
      struct nonmatching_ref_data: store a refname instead of a ref_entry
      is_refname_available(): use dirname in first loop
      ref_transaction_commit(): use a string_list for detecting duplicates
      refs: check for D/F conflicts among refs created in a transaction
      verify_refname_available(): rename function
      verify_refname_available(): report errors via a "struct strbuf *err"
      lock_ref_sha1_basic(): report errors via a "struct strbuf *err"
      lock_ref_sha1_basic(): improve diagnostics for ref D/F conflicts
      rename_ref(): integrate lock_ref_sha1_basic() errors into ours
      ref_transaction_commit(): provide better error messages
      ref_transaction_commit(): delete extra "the" from error message
      reflog_expire(): integrate lock_ref_sha1_basic() errors into ours
      write_ref_to_lockfile(): new function, extracted from write_ref_sha1()
      commit_ref_update(): new function, extracted from write_ref_sha1()
      rename_ref(): inline calls to write_ref_sha1() from this function
      ref_transaction_commit(): inline call to write_ref_sha1()
      ref_transaction_commit(): remove the local flags variable
      ref_transaction_commit(): fix atomicity and avoid fd exhaustion
      write_ref_to_lockfile(): new function, extracted from write_ref_sha1()
      commit_ref_update(): new function, extracted from write_ref_sha1()
      rename_ref(): inline calls to write_ref_sha1() from this function
      ref_transaction_commit(): inline call to write_ref_sha1()
      ref_transaction_commit(): remove the local flags variable
      ref_transaction_commit(): fix atomicity and avoid fd exhaustion
      lockfile: allow file locking to be retried with a timeout
      lock_packed_refs(): allow retries when acquiring the packed-refs lock
      each_ref_fn: change to take an object_id parameter
      builtin/rev-parse: rewrite to take an object_id argument
      handle_one_ref(): rewrite to take an object_id argument
      register_ref(): rewrite to take an object_id argument
      append_ref(): rewrite to take an object_id argument
      add_pending_uninteresting_ref(): rewrite to take an object_id argument
      get_name(): rewrite to take an object_id argument
      builtin/fetch: rewrite to take an object_id argument
      grab_single_ref(): rewrite to take an object_id argument
      name_ref(): rewrite to take an object_id argument
      builtin/pack-objects: rewrite to take an object_id argument
      show_ref_cb(): rewrite to take an object_id argument
      builtin/reflog: rewrite ref functions to take an object_id argument
      add_branch_for_removal(): rewrite to take an object_id argument
      add_branch_for_removal(): don't set "util" field of string_list entries
      builtin/remote: rewrite functions to take object_id arguments
      show_reference(): rewrite to take an object_id argument
      append_matching_ref(): rewrite to take an object_id argument
      builtin/show-branch: rewrite functions to take object_id arguments
      append_one_rev(): rewrite to work with object_id
      builtin/show-branch: rewrite functions to work with object_id
      cmd_show_branch(): fix error message
      fsck: change functions to use object_id
      builtin/show-ref: rewrite to use object_id
      show_ref(): convert local variable peeled to object_id
      builtin/show-ref: rewrite to take an object_id argument
      append_similar_ref(): rewrite to take an object_id argument
      http-backend: rewrite to take an object_id argument
      show_head_ref(): convert local variable "unused" to object_id
      add_ref_decoration(): rewrite to take an object_id argument
      add_ref_decoration(): convert local variable original_sha1 to object_id
      string_list_add_one_ref(): rewrite to take an object_id argument
      add_one_ref(): rewrite to take an object_id argument
      remote: rewrite functions to take object_id arguments
      register_replace_ref(): rewrite to take an object_id argument
      handle_one_reflog(): rewrite to take an object_id argument
      add_info_ref(): rewrite to take an object_id argument
      handle_one_ref(): rewrite to take an object_id argument
      shallow: rewrite functions to take object_id arguments
      submodule: rewrite to take an object_id argument
      write_refs_to_temp_dir(): convert local variable sha1 to object_id
      write_one_ref(): rewrite to take an object_id argument
      find_symref(): rewrite to take an object_id argument
      find_symref(): convert local variable "unused" to object_id
      upload-pack: rewrite functions to take object_id arguments
      send_ref(): convert local variable "peeled" to object_id
      mark_complete(): rewrite to take an object_id argument
      clear_marks(): rewrite to take an object_id argument
      mark_complete_oid(): new function, taking an object_oid
      mark_complete(): remove unneeded arguments
      rev_list_insert_ref_oid(): new function, taking an object_oid
      rev_list_insert_ref(): remove unneeded arguments
      each_ref_fn_adapter(): remove adapter
      warn_if_dangling_symref(): convert local variable "junk" to object_id
      struct ref_lock: convert old_sha1 member to object_id
      verify_lock(): return 0/-1 rather than struct ref_lock *
      verify_lock(): on errors, let the caller unlock the lock
      verify_lock(): report errors via a strbuf
      verify_lock(): do not capitalize error messages
      ref_transaction_commit(): do not capitalize error messages
      t6301: new tests of for-each-ref error handling
      for-each-ref: report broken references correctly
      read_loose_refs(): simplify function logic
      read_loose_refs(): treat NULL_SHA1 loose references as broken
      fsck_handle_reflog_sha1(): new function
      fsck: report errors if reflog entries point at invalid objects
      strbuf: strbuf_read_file() should return ssize_t

Michael J Gruber (4):
      l10n: de.po: grammar fix
      l10n: de.po: punctuation fixes
      l10n: de.po: translation fix for fall-back to 3way merge
      mergetool-lib: fix default tool selection

Miguel Torroja (1):
      p4: retrieve the right revision of the file in UTF-16 codepath

Mike Edgar (1):
      fetch-pack: check for shallow if depth given

Mike Hommey (2):
      show-branch: show all local heads when only giving one rev along --topics
      clone: call transport_set_verbosity before anything else on the newly created transport

Nguyễn Thái Ngọc Duy (67):
      path.c: make get_pathname() return strbuf instead of static buffer
      path.c: make get_pathname() call sites return const char *
      git_snpath(): retire and replace with strbuf_git_path()
      path.c: rename vsnpath() to do_git_path()
      path.c: group git_path(), git_pathdup() and strbuf_git_path() together
      git_path(): be aware of file relocation in $GIT_DIR
      *.sh: respect $GIT_INDEX_FILE
      reflog: avoid constructing .lock path with git_path
      fast-import: use git_path() for accessing .git dir instead of get_git_dir()
      commit: use SEQ_DIR instead of hardcoding "sequencer"
      $GIT_COMMON_DIR: a new environment variable
      git-sh-setup.sh: use rev-parse --git-path to get $GIT_DIR/objects
      *.sh: avoid hardcoding $GIT_DIR/hooks/...
      git-stash: avoid hardcoding $GIT_DIR/logs/....
      setup.c: convert is_git_directory() to use strbuf
      setup.c: detect $GIT_COMMON_DIR in is_git_directory()
      setup.c: convert check_repository_format_gently to use strbuf
      setup.c: detect $GIT_COMMON_DIR check_repository_format_gently()
      setup.c: support multi-checkout repo setup
      wrapper.c: wrapper to open a file, fprintf then close
      use new wrapper write_file() for simple file writing
      checkout: support checking out into a new working directory
      prune: strategies for linked checkouts
      checkout: reject if the branch is already checked out elsewhere
      checkout: clean up half-prepared directories in --to mode
      gc: style change -- no SP before closing parenthesis
      gc: factor out gc.pruneexpire parsing code
      gc: support prune --worktrees
      count-objects: report unused files in $GIT_DIR/worktrees/...
      git_path(): keep "info/sparse-checkout" per work-tree
      t2025: add a test to make sure grafts is working from a linked checkout
      checkout: pass whole struct to parse_branchname_arg instead of individual flags
      checkout: add --ignore-other-wortrees
      git-checkout.txt: a note about multiple checkout support for submodules
      index-pack: reduce object_entry size to save memory
      dir.c: optionally compute sha-1 of a .gitignore file
      untracked cache: record .gitignore information and dir hierarchy
      untracked cache: initial untracked cache validation
      untracked cache: invalidate dirs recursively if .gitignore changes
      untracked cache: make a wrapper around {open,read,close}dir()
      untracked cache: record/validate dir mtime and reuse cached output
      untracked cache: mark what dirs should be recursed/saved
      untracked cache: don't open non-existent .gitignore
      ewah: add convenient wrapper ewah_serialize_strbuf()
      untracked cache: save to an index extension
      untracked cache: load from UNTR index extension
      untracked cache: invalidate at index addition or removal
      read-cache.c: split racy stat test to a separate function
      untracked cache: avoid racy timestamps
      untracked cache: print stats with $GIT_TRACE_UNTRACKED_STATS
      untracked cache: mark index dirty if untracked cache is updated
      untracked-cache: temporarily disable with $GIT_DISABLE_UNTRACKED_CACHE
      status: enable untracked cache
      update-index: manually enable or disable untracked cache
      update-index: test the system before enabling untracked cache
      t7063: tests for untracked cache
      mingw32: add uname()
      untracked cache: guard and disable on system changes
      git-status.txt: advertisement for untracked cache
      diff-lib.c: adjust position of i-t-a entries in diff
      index-pack: kill union delta_base to save memory
      t1509: update prepare script to be able to run t1509 in chroot again
      pathspec: avoid the need of "--" when wildcard is used
      read-cache: fix untracked cache invalidation when split-index is used
      checkout: don't check worktrees when not necessary
      worktree: new place for "git prune --worktrees"
      Add tests for wildcard "path vs ref" disambiguation

Ossi Herrala (1):
      config: fix settings in default_user_config template

Panagiotis Astithas (1):
      hooks/pre-auto-gc: adjust power checking for newer OS X

Patrick Steinhardt (5):
      bundle: verify arguments more strictly
      git-verify-pack.txt: fix inconsistent spelling of "packfile"
      git-unpack-objects.txt: fix inconsistent spelling of "packfile"
      pack-protocol.txt: fix insconsistent spelling of "packfile"
      doc: fix inconsistent spelling of "packfile"

Paul Tan (31):
      git-credential-store: support multiple credential files
      git-credential-store: support XDG_CONFIG_HOME
      t0302: test credential-store support for XDG_CONFIG_HOME
      path.c: implement xdg_config_home()
      attr.c: replace home_config_paths() with xdg_config_home()
      dir.c: replace home_config_paths() with xdg_config_home()
      credential-store.c: replace home_config_paths() with xdg_config_home()
      git-commit: replace use of home_config_paths()
      git-config: replace use of home_config_paths()
      path.c: remove home_config_paths()
      pull: remove --tags error in no merge candidates case
      t5520: prevent field splitting in content comparisons
      t5520: test no merge candidates cases
      pull: handle --log=<n>
      pull: make pull.ff=true override merge.ff
      pull: parse pull.ff as a bool or string
      t5520: test for failure if index has unresolved entries
      t5520: test work tree fast-forward when fetch updates head
      t5520: test --rebase with multiple branches
      t5520: test --rebase failure on unborn branch with index
      t5521: test --dry-run does not make any changes
      t5520: check reflog action in fast-forward merge
      pull: handle git-fetch's options as well
      pull: use git-rev-parse --parseopt for option parsing
      am --skip: revert changes introduced by failed 3way merge
      am -3: support 3way merge on unborn branch
      am --skip: support skipping while on unborn branch
      am --abort: revert changes introduced by failed 3way merge
      am --abort: support aborting to unborn branch
      am --abort: keep unrelated commits on unborn branch
      t0302: "unreadable" test needs SANITY prereq

Peter Krefting (2):
      l10n: sv.po: Update Swedish translation (2355t0f0u)
      l10n: sv.po: Update Swedish translation (2359t0f0u)

Phil Hord (1):
      rebase -i: redo tasks that die during cherry-pick

Phillip Sz (1):
      l10n: de.po: change error message from "sagen" to "Meinten Sie"

Quentin Neill (1):
      blame: add blame.showEmail configuration

Ralf Thielow (4):
      l10n: de.po: fix translation of "head nodes"
      l10n: de.po: translate "index" as "Index"
      l10n: de.po: translate 65 new messages
      l10n: de.po: translate 9 new messages

Ramsay Allan Jones (1):
      t7502-commit.sh: fix a broken and-chain

Remi Lespinet (3):
      git-am.sh: fix initialization of the threeway variable
      t4150-am: refactor am -3 tests
      git-am: add am.threeWay config variable

René Scharfe (5):
      pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps
      use file_exists() to check if a file exists in the worktree
      clean: remove unused variable buf
      dir: remove unused variable sb
      diff: parse ws-error-highlight option more strictly

Richard Hansen (2):
      Revert "test-lib.sh: do tests for color support after changing HOME"
      test-lib.sh: fix color support when tput needs ~/.terminfo

SZEDER Gábor (8):
      completion: remove redundant __git_compute_all_commands() call
      completion: fix and update 'git log --decorate=' options
      completion: remove credential helpers from porcelain commands
      completion: add a helper function to get config variables
      completion: simplify query for config variables
      Documentation: include 'merge.branchdesc' for merge and config as well
      completion: teach 'scissors' mode to 'git commit --cleanup='
      commit: cope with scissors lines in commit message

Sebastian Schuberth (1):
      clone: simplify string handling in guess_dir_name()

Stefan Beller (14):
      line-log.c: fix a memleak
      pack-bitmap.c: fix a memleak
      prefix_path(): unconditionally free results in the callers
      update-ref: test handling large transactions properly
      refs.c: remove lock_fd from struct ref_lock
      t7004: rename ULIMIT test prerequisite to ULIMIT_STACK_SIZE
      update-ref: test handling large transactions properly
      t7004: rename ULIMIT test prerequisite to ULIMIT_STACK_SIZE
      subdirectory tests: code cleanup, uncomment test
      submodule doc: reorder introductory paragraphs
      glossary: add "remote", "submodule", "superproject"
      Documentation/technical/pack-protocol: mention http as possible protocol
      p5310: Fix broken && chain in performance test
      revision.c: remove unneeded check for NULL

Sébastien Guimmara (4):
      command-list.txt: fix whitespace inconsistency
      command-list.txt: add the common groups block
      command-list.txt: drop the "common" tag
      help: respect new common command grouping

Thomas Braun (1):
      completion: suggest sequencer commands for revert

Thomas Gummerer (1):
      t1501: fix test with split index

Thomas Schneider (1):
      checkout: call a single commit "it" intead of "them"

Tony Finch (1):
      gitweb: fix typo in man page

Torsten Bögershausen (6):
      t2026 needs procondition SANITY
      t0027: cleanup: rename functions; avoid non-leading TABs
      t0027: support NATIVE_CRLF platforms
      t0027: Add repoMIX and LF_nul
      blame: CRLF in the working tree and LF in the repo
      git-checkout.txt: document "git checkout <pathspec>" better

Trần Ngọc Quân (2):
      l10n: Updated Vietnamese translation (2355t)
      l10n: Updated Vietnamese translation (2359t)

Vitor Antunes (2):
      t9801: check git-p4's branch detection with client spec enabled
      git-p4: improve client path detection when branches are used

brian m. carlson (14):
      define a structure for object IDs
      define utility functions for object IDs
      bisect.c: convert leaf functions to use struct object_id
      archive.c: convert to use struct object_id
      zip: use GIT_SHA1_HEXSZ for trailers
      bulk-checkin.c: convert to use struct object_id
      diff: convert struct combine_diff_path to object_id
      commit: convert parts to struct object_id
      patch-id: convert to use struct object_id
      apply: convert threeway_stage to object_id
      connect: simplify SSH connection code path
      t5601: fix quotation error leading to skipped tests
      connect: improve check for plink to reduce false positives
      refs: convert struct ref_entry to use struct object_id

^ permalink raw reply	[relevance 1%]

* [PATCH] add: remove dead code
@ 2015-07-31  0:19  7% Stefan Beller
  2015-07-31 16:41  5% ` Junio C Hamano
                   ` (3 more replies)
  0 siblings, 4 replies; 200+ results
From: Stefan Beller @ 2015-07-31  0:19 UTC (permalink / raw)
  To: gitster; +Cc: git, Stefan Beller

Signed-off-by: Stefan Beller <sbeller@google.com>
---

So I was trying to understand how to implement "git add .gitmodules" as 
I intend to rewrite git submodules in C.

 builtin/add.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/builtin/add.c b/builtin/add.c
index 4bd98b7..b2a5c57 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -375,7 +375,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (add_new_files) {
 		int baselen;
-		struct pathspec empty_pathspec;
 
 		/* Set up the default git porcelain excludes */
 		memset(&dir, 0, sizeof(dir));
@@ -384,7 +383,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 			setup_standard_excludes(&dir);
 		}
 
-		memset(&empty_pathspec, 0, sizeof(empty_pathspec));
 		/* This picks up the paths that are not tracked */
 		baselen = fill_directory(&dir, &pathspec);
 		if (pathspec.nr)
-- 
2.5.0.rc1.391.g15b60ce

^ permalink raw reply related	[relevance 7%]

* Re: [PATCH] add: remove dead code
  2015-07-31  0:19  7% [PATCH] add: remove dead code Stefan Beller
@ 2015-07-31 16:41  5% ` Junio C Hamano
  2015-07-31 23:09 10% ` [RFC/PATCH 0/2] Submodules: refactoring the `module_list` function Stefan Beller
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-07-31 16:41 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, Jens Lehmann, Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>
> So I was trying to understand how to implement "git add .gitmodules" as 
> I intend to rewrite git submodules in C.

A request and a suggestion.

 - Please keep Jens and Heiko in the loop and pick their brains ;-)

 - It may not be the best use of your time to attempt rewriting the
   whole of "git submodule" in C in a single pass (which is the
   impression I am getting from seeing you say "git add
   .gitmodules").

   The largest pain point a rewrite in C would solve is that "git
   submodule init" and "update" have to go sequencially even though

   (1) there is no inherent reason for cloning and fetching of
       different submodules to happen in some order;

   (2) there is no inherent reason for a failure to clone or fetch
       of one submodule to abort the entire session without cloning
       or fetching other submodules; and

   (3) the operation in each submodule takes human-scale time and
       the users would benefit greatly by parallel operations.

   One approach that may be beneficial would be to introduce "git
   submodule--helper" written in C to have selected primitives used
   in "git submodule" script to speed them up.  Perhaps the first
   subcommand would be "

    $ git submodule--helper foreach-parallel --cmd=$cmd $args...

   where it takes the arguments currently fed to module_list as
   $args... and runs $cmd in parallel.  The initial implementation
   of "git submodule update" then would replace the expensive and
   sequencial

       module_list "$@" | {
           ...
           while read mode sha1 stage sm_path
           do
           	...
	   done
       }

   loop with a call to the foreach-parallel subcommand.

   The end-user scripts that currently use "git submodule foreach"
   may or may not depend on the sequencial nature of the current
   implementation, so adding "git submodule foreach-parallel" may be
   a good way to expose this as a new "do it in parallel" feature.

   Once you have a solid infrastructure to implement the helper
   subcommand "foreach-parallel" (I'd expect the interface inside C
   into that function would be to give it a worker function with the
   data for the function to consume, and the above --cmd=$cmd form
   would use a worker function that essentially does run_command();
   the spawn(2)ing and wait(2)ing would be done on the more generic
   API side), you can rewrite the $cmd part in C little by little,
   and eventually you would get a full C implemention while keeping
   everything working and retaining debuggability during the course
   of development.

Thanks.

^ permalink raw reply	[relevance 5%]

* [RFC/PATCH 0/2] Submodules: refactoring the `module_list` function
  2015-07-31  0:19  7% [PATCH] add: remove dead code Stefan Beller
  2015-07-31 16:41  5% ` Junio C Hamano
@ 2015-07-31 23:09 10% ` Stefan Beller
  2015-07-31 23:09 14% ` [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper Stefan Beller
  2015-07-31 23:09 17% ` [RFC/PATCH 2/2] Testing the new code Stefan Beller
  3 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-07-31 23:09 UTC (permalink / raw)
  To: git; +Cc: Stefan Beller, Jens.Lehmann, hvoigt, gitster

Hi,

so eventually we want to have the whole Android project inside a git repository,
which includes > 500 submodules for the different sub systems. To make that feasable
we want to improve git-submodule for a huge set of submodules such as parallelizing
`git submodule update`. As a first step I was toying around the `module_list` function
as that is one key component for all the submodule operations. Also that part of the
code is where the operations are split up to the different submodules, so that
would be the natural place where we'd approach introducing threads later on.

This is an early RFC as it breaks the test suite. I do not remember ever interacting
with pathspecs or cache entries before, so I'd appreciate some guiding comments.
(Am I holding it wrong? Also the git code base seems large, it's easy to find new
playgrounds :)

Thanks,
Stefan

Stefan Beller (2):
  submodule: implement `module_list` as a builtin helper
  Testing the new code

 Makefile                    |  1 +
 builtin.h                   |  1 +
 builtin/submodule--helper.c | 99 +++++++++++++++++++++++++++++++++++++++++++++
 git-submodule.sh            | 25 +++++++++++-
 git.c                       |  1 +
 5 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 builtin/submodule--helper.c

-- 
2.5.0.5.gf4cd9ae.dirty

^ permalink raw reply	[relevance 10%]

* [RFC/PATCH 2/2] Testing the new code
  2015-07-31  0:19  7% [PATCH] add: remove dead code Stefan Beller
                   ` (2 preceding siblings ...)
  2015-07-31 23:09 14% ` [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper Stefan Beller
@ 2015-07-31 23:09 17% ` Stefan Beller
  2015-08-01  1:02  2%   ` Junio C Hamano
  3 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-07-31 23:09 UTC (permalink / raw)
  To: git; +Cc: Stefan Beller, Jens.Lehmann, hvoigt, gitster

Signed-off-by: Stefan Beller <sbeller@google.com>
---

Notes:
    The output of the differential testing is below,
    which points out 2 bugs:
    * resolving relative paths seems is broken, so we
      would need to have the equivalent of
        eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
      (091a6eb0, 2013-06-16,  submodule: drop the top-level requirement)
    * The handling of funny characters is broken.
    
    ----------------------------------------------
    ../init
    160000 9ab41d0d44279924747e3eafa6da77966579aa45 0	init
    ----
    ----
    ----
    fatal: ../init: '../init' is outside repository
    ----------------------------------------------
    ../init
    160000 37b832c3ae4dcc0830b173572ff59be6b089bdcd 0	init
    ----
    ----
    ----
    fatal: ../init: '../init' is outside repository
    ----------------------------------------------
    ../init
    160000 9ab41d0d44279924747e3eafa6da77966579aa45 0	init
    ----
    ----
    ----
    fatal: ../init: '../init' is outside repository
    ----------------------------------------------
    
    160000 37b832c3ae4dcc0830b173572ff59be6b089bdcd 0	example2
    160000 9ab41d0d44279924747e3eafa6da77966579aa45 0	init
    160000 01b25b1d44b1049978e053768790100df8b8d9d9 0	å äö
    ----
    160000 37b832c3ae4dcc0830b173572ff59be6b089bdcd 0	example2
    160000 9ab41d0d44279924747e3eafa6da77966579aa45 0	init
    160000 01b25b1d44b1049978e053768790100df8b8d9d9 0	"\303\245 \303\244\303\266"
    ----
    ----

 git-submodule.sh | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 36797c3..717b74d 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -149,7 +149,7 @@ relative_path ()
 # Get submodule info for registered submodules
 # $@ = path to limit submodule list
 #
-module_list()
+module_list_shell()
 {
 	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
 	(
@@ -187,6 +187,29 @@ module_list()
 	'
 }
 
+module_list()
+{
+	# call both the old and new code
+	module_list_shell $@ >/u/git_submodule_module_list_shell 2>/u/git_submodule_module_list_shell2
+	git submodule--helper --module_list $@ >/u/git_submodule_module_list 2>/u/git_submodule_module_list2
+	# if there is a diff record it
+	DIFF=$(diff /u/git_submodule_module_list_shell /u/git_submodule_module_list)
+	if [ "$DIFF" != "" ]
+	then
+		echo "----------------------------------------------">>/u/git_submodule_module_diffs
+		echo $@ >>/u/git_submodule_module_diffs
+		cat /u/git_submodule_module_list_shell >>/u/git_submodule_module_diffs
+		echo "----" >>/u/git_submodule_module_diffs
+		cat /u/git_submodule_module_list >>/u/git_submodule_module_diffs
+		echo "----" >>/u/git_submodule_module_diffs
+		cat /u/git_submodule_module_list_shell2 >>/u/git_submodule_module_diffs
+		echo "----" >>/u/git_submodule_module_diffs
+		cat /u/git_submodule_module_list2 >>/u/git_submodule_module_diffs
+	fi
+	# output to the caller
+	cat /u/git_submodule_module_list
+}
+
 die_if_unmatched ()
 {
 	if test "$1" = "#unmatched"
-- 
2.5.0.5.gf4cd9ae.dirty

^ permalink raw reply related	[relevance 17%]

* [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper
  2015-07-31  0:19  7% [PATCH] add: remove dead code Stefan Beller
  2015-07-31 16:41  5% ` Junio C Hamano
  2015-07-31 23:09 10% ` [RFC/PATCH 0/2] Submodules: refactoring the `module_list` function Stefan Beller
@ 2015-07-31 23:09 14% ` Stefan Beller
  2015-08-01  1:01  7%   ` Junio C Hamano
  2015-07-31 23:09 17% ` [RFC/PATCH 2/2] Testing the new code Stefan Beller
  3 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-07-31 23:09 UTC (permalink / raw)
  To: git; +Cc: Stefan Beller, Jens.Lehmann, hvoigt, gitster

Most of the submodule operations work on a set of submodules.
Calculating and using this set is usually done via:

       module_list "$@" | {
           while read mode sha1 stage sm_path
           do
                # the actual operation
           done
       }

Currently the function `module_list` is implemented in the
git-submodule.sh as a shell script wrapping a perl script.
The rewrite is in C, such that it is faster and can later be
easily adapted when other functions are rewritten in C.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Makefile                    |  1 +
 builtin.h                   |  1 +
 builtin/submodule--helper.c | 99 +++++++++++++++++++++++++++++++++++++++++++++
 git.c                       |  1 +
 4 files changed, 102 insertions(+)
 create mode 100644 builtin/submodule--helper.c

diff --git a/Makefile b/Makefile
index 8c3c724..6fb7484 100644
--- a/Makefile
+++ b/Makefile
@@ -898,6 +898,7 @@ BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
 BUILTIN_OBJS += builtin/stripspace.o
+BUILTIN_OBJS += builtin/submodule--helper.o
 BUILTIN_OBJS += builtin/symbolic-ref.o
 BUILTIN_OBJS += builtin/tag.o
 BUILTIN_OBJS += builtin/unpack-file.o
diff --git a/builtin.h b/builtin.h
index 9e04f97..7bf9597 100644
--- a/builtin.h
+++ b/builtin.h
@@ -118,6 +118,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
 extern int cmd_status(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
+extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_tag(int argc, const char **argv, const char *prefix);
 extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
new file mode 100644
index 0000000..2e24fdc
--- /dev/null
+++ b/builtin/submodule--helper.c
@@ -0,0 +1,99 @@
+#include "builtin.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "quote.h"
+#include "pathspec.h"
+#include "dir.h"
+
+static const char * const git_submodule_helper_usage[] = {
+	N_("git submodule--helper --module_list [<path>...]"),
+	NULL
+};
+
+int module_list(int argc, const char **argv, const char *prefix)
+{
+	int i;
+	static struct pathspec pathspec;
+	const struct cache_entry **ce_entries = NULL;
+	int alloc = 0, used = 0;
+	char *ps_matched = NULL;
+	char *max_prefix;
+	int max_prefix_len;
+	struct string_list already_printed = STRING_LIST_INIT_NODUP;
+
+	parse_pathspec(&pathspec, 0,
+		       PATHSPEC_PREFER_FULL,
+		       prefix, argv);
+
+	/* Find common prefix for all pathspec's */
+	max_prefix = common_prefix(&pathspec);
+	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
+
+	if (pathspec.nr)
+		ps_matched = xcalloc(1, pathspec.nr);
+
+	if (read_cache() < 0)
+		die("index file corrupt");
+
+	for (i = 0; i < active_nr; i++) {
+		const struct cache_entry *ce = active_cache[i];
+
+		if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
+				    max_prefix_len, ps_matched,
+				    S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode)))
+			continue;
+
+		if (S_ISGITLINK(ce->ce_mode)) {
+			ALLOC_GROW(ce_entries, used + 1, alloc);
+			ce_entries[used++] = ce;
+		}
+	}
+
+	if (ps_matched && report_path_error(ps_matched, &pathspec, prefix)) {
+		printf("#unmatched\n");
+		return 1;
+	}
+
+	for (i = 0; i < used; i++) {
+		const struct cache_entry *ce = ce_entries[i];
+
+		if (string_list_has_string(&already_printed, ce->name))
+			continue;
+
+		if (ce_stage(ce)) {
+			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
+		} else {
+			printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce));
+		}
+		write_name_quoted(ce->name, stdout, '\n');
+		string_list_insert(&already_printed, ce->name);
+	}
+	return 0;
+}
+
+int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
+{
+	enum {
+		MODE_UNSPECIFIED = 0,
+		MODE_MODULE_LIST,
+	} cmdmode = MODE_UNSPECIFIED;
+
+	struct option options[] = {
+		OPT_CMDMODE(0, "module_list", &cmdmode,
+			    N_("Get the submodule list"), MODE_MODULE_LIST),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options,
+			     git_submodule_helper_usage, 0);
+
+	switch (cmdmode) {
+	case MODE_MODULE_LIST:
+		return module_list(argc, argv, prefix);
+		break;
+	case MODE_UNSPECIFIED:
+		usage_with_options(git_submodule_helper_usage, options);
+		break;
+	}
+	return 0;
+}
diff --git a/git.c b/git.c
index fe94066..721995e 100644
--- a/git.c
+++ b/git.c
@@ -468,6 +468,7 @@ static struct cmd_struct commands[] = {
 	{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 	{ "stripspace", cmd_stripspace },
+	{ "submodule--helper", cmd_submodule__helper, RUN_SETUP },
 	{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
 	{ "tag", cmd_tag, RUN_SETUP },
 	{ "unpack-file", cmd_unpack_file, RUN_SETUP },
-- 
2.5.0.5.gf4cd9ae.dirty

^ permalink raw reply related	[relevance 14%]

* Re: [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper
  2015-07-31 23:09 14% ` [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper Stefan Beller
@ 2015-08-01  1:01  7%   ` Junio C Hamano
  2015-08-03 21:30  7%     ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-08-01  1:01 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, Jens.Lehmann, hvoigt

Stefan Beller <sbeller@google.com> writes:

> +static const char * const git_submodule_helper_usage[] = {
> +	N_("git submodule--helper --module_list [<path>...]"),

Yuck.  Please do not force --multi_word_opt upon us, which is simply
too ugly to live around here.  --module-list is perhaps OK, but
because submodule--helper would not have an default action, I'd
prefer to make these just "command words", i.e.

    $ git submodule--helper module_list

> +int module_list(int argc, const char **argv, const char *prefix)
> +{
> +	int i;
> +	static struct pathspec pathspec;
> +	const struct cache_entry **ce_entries = NULL;
> +	int alloc = 0, used = 0;
> +	char *ps_matched = NULL;
> +	char *max_prefix;
> +	int max_prefix_len;
> +	struct string_list already_printed = STRING_LIST_INIT_NODUP;
> +
> +	parse_pathspec(&pathspec, 0,
> +		       PATHSPEC_PREFER_FULL,
> +		       prefix, argv);
> +
> +	/* Find common prefix for all pathspec's */
> +	max_prefix = common_prefix(&pathspec);
> +	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
> +
> +	if (pathspec.nr)
> +		ps_matched = xcalloc(1, pathspec.nr);

Up to this point it interprets its input, and ...

> +	if (read_cache() < 0)
> +		die("index file corrupt");
> +
> +	for (i = 0; i < active_nr; i++) {
> +		const struct cache_entry *ce = active_cache[i];
> +
> +		if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
> +				    max_prefix_len, ps_matched,
> +				    S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode)))
> +			continue;
> +
> +		if (S_ISGITLINK(ce->ce_mode)) {
> +			ALLOC_GROW(ce_entries, used + 1, alloc);
> +			ce_entries[used++] = ce;
> +		}
> +	}
> +
> +	if (ps_matched && report_path_error(ps_matched, &pathspec, prefix)) {
> +		printf("#unmatched\n");
> +		return 1;
> +	}

... does the computation, with diagnosis.

And then it does the I/O with formatting.

> +
> +	for (i = 0; i < used; i++) {
> +		const struct cache_entry *ce = ce_entries[i];
...
> +	return 0;
> +}

When you have the implementation of "foreach-parallel" to move the
most expensive part of "submodule update" of a tree with 500
submodules, you would want to receive more or less the same "args"
as this thing takes and pass the ce_entries[] list to the "spawn and
run the user script in them in parallel" engine.

So I think it makes more sense to split this function into two (or
three).  One that reads from (argc, argv) and allocates and fills
ce_entries[] can become a helper that you can reuse later.  

'int module_list()' (shouldn't it be static?), can make a call to
that helper at the begining of it, and the remainder of the function
would do the textual I/O.

^ permalink raw reply	[relevance 7%]

* Re: [RFC/PATCH 2/2] Testing the new code
  2015-07-31 23:09 17% ` [RFC/PATCH 2/2] Testing the new code Stefan Beller
@ 2015-08-01  1:02  2%   ` Junio C Hamano
  2015-08-03 16:23  2%     ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-08-01  1:02 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, Jens.Lehmann, hvoigt

Stefan Beller <sbeller@google.com> writes:

> -module_list()
> +module_list_shell()
>  {
>  	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
>  	(
> @@ -187,6 +187,29 @@ module_list()
>  	'
>  }
>  
> +module_list()
> +{
> +	# call both the old and new code
> +	module_list_shell $@ >/u/git_submodule_module_list_shell 2>/u/git_submodule_module_list_shell2
> +	git submodule--helper --module_list $@ >/u/git_submodule_module_list 2>/u/git_submodule_module_list2

You seem to be discarding the double-quote around $@ in both of
these two places.  Intended?

^ permalink raw reply	[relevance 2%]

* Re: [RFC/PATCH 2/2] Testing the new code
  2015-08-01  1:02  2%   ` Junio C Hamano
@ 2015-08-03 16:23  2%     ` Stefan Beller
  2015-08-03 19:47  2%       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-03 16:23 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org, Jens Lehmann, Heiko Voigt

On Fri, Jul 31, 2015 at 6:02 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> -module_list()
>> +module_list_shell()
>>  {
>>       eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
>>       (
>> @@ -187,6 +187,29 @@ module_list()
>>       '
>>  }
>>
>> +module_list()
>> +{
>> +     # call both the old and new code
>> +     module_list_shell $@ >/u/git_submodule_module_list_shell 2>/u/git_submodule_module_list_shell2
>> +     git submodule--helper --module_list $@ >/u/git_submodule_module_list 2>/u/git_submodule_module_list2
>
> You seem to be discarding the double-quote around $@ in both of
> these two places.  Intended?

No, not at all. This was a bit sloppy.
This patch was rather showing off how I intend to test the previous patch.
The idea came from a talk[1] at oscon which presented refactoring code with
this differential strategy (except that they used it on a larger code base and
collected the diffs between the new and old code for a while in production
instead of just relying on the test suite passing).

[1] http://www.oscon.com/open-source-2015/public/schedule/detail/41888

^ permalink raw reply	[relevance 2%]

* [PATCH] builtin/mv: Get rid of the last caller of get_pathspec
@ 2015-08-03 17:53  5% Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-03 17:53 UTC (permalink / raw)
  To: git
  Cc: Stefan Beller, Johannes Schindelin, Junio C Hamano,
	Nguyễn Thái Ngọc Duy

`get_pathspec` is deprecated and builtin/mv is its last caller, so getting
rid of `get_pathspec` is rather easy. By getting rid of `get_pathspec`,
the documentation such as 'technical/api-setup.txt' becomes easier to read
as the reader doesn't need to bear with the additional fact that
`get_pathspec` is deprecated.

The code in 'builtin/mv' still requires some work to make it less ugly.

CC: Johannes Schindelin <Johannes.Schindelin@gmx.de>
CC: Junio C Hamano <gitster@pobox.com>
CC: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Documentation/technical/api-setup.txt |  2 --
 builtin/mv.c                          | 19 ++++++++++++++++---
 cache.h                               |  1 -
 pathspec.c                            | 30 ------------------------------
 4 files changed, 16 insertions(+), 36 deletions(-)

diff --git a/Documentation/technical/api-setup.txt b/Documentation/technical/api-setup.txt
index 540e455..eb1fa98 100644
--- a/Documentation/technical/api-setup.txt
+++ b/Documentation/technical/api-setup.txt
@@ -27,8 +27,6 @@ parse_pathspec(). This function takes several arguments:
 
 - prefix and args come from cmd_* functions
 
-get_pathspec() is obsolete and should never be used in new code.
-
 parse_pathspec() helps catch unsupported features and reject them
 politely. At a lower level, different pathspec-related functions may
 not support the same set of features. Such pathspec-sensitive
diff --git a/builtin/mv.c b/builtin/mv.c
index d1d4316..b89d90a 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -10,6 +10,7 @@
 #include "string-list.h"
 #include "parse-options.h"
 #include "submodule.h"
+#include "pathspec.h"
 
 static const char * const builtin_mv_usage[] = {
 	N_("git mv [<options>] <source>... <destination>"),
@@ -20,13 +21,19 @@ static const char * const builtin_mv_usage[] = {
 #define KEEP_TRAILING_SLASH 2
 
 static const char **internal_copy_pathspec(const char *prefix,
-					   const char **pathspec,
+					   const char **argv,
 					   int count, unsigned flags)
 {
 	int i;
+	struct pathspec ps;
 	const char **result = xmalloc((count + 1) * sizeof(const char *));
-	memcpy(result, pathspec, count * sizeof(const char *));
+	memcpy(result, argv, count * sizeof(const char *));
 	result[count] = NULL;
+
+	/*
+	 * NEEDSWORK: instead of preprocessing, pass the right flags to
+	 * parse_pathspec below.
+	 */
 	for (i = 0; i < count; i++) {
 		int length = strlen(result[i]);
 		int to_copy = length;
@@ -42,7 +49,13 @@ static const char **internal_copy_pathspec(const char *prefix,
 				result[i] = it;
 		}
 	}
-	return get_pathspec(prefix, result);
+
+	parse_pathspec(&ps,
+		       PATHSPEC_ALL_MAGIC &
+		       ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
+		       PATHSPEC_PREFER_CWD,
+		       prefix, result);
+	return ps._raw;
 }
 
 static const char *add_slash(const char *path)
diff --git a/cache.h b/cache.h
index 4f55466..d4e22e2 100644
--- a/cache.h
+++ b/cache.h
@@ -452,7 +452,6 @@ extern void set_git_work_tree(const char *tree);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
-extern const char **get_pathspec(const char *prefix, const char **pathspec);
 extern void setup_work_tree(void);
 extern const char *setup_git_directory_gently(int *);
 extern const char *setup_git_directory(void);
diff --git a/pathspec.c b/pathspec.c
index 9304ee3..b0e14e5 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -450,36 +450,6 @@ void parse_pathspec(struct pathspec *pathspec,
 	}
 }
 
-/*
- * N.B. get_pathspec() is deprecated in favor of the "struct pathspec"
- * based interface - see pathspec.c:parse_pathspec().
- *
- * Arguments:
- *  - prefix - a path relative to the root of the working tree
- *  - pathspec - a list of paths underneath the prefix path
- *
- * Iterates over pathspec, prepending each path with prefix,
- * and return the resulting list.
- *
- * If pathspec is empty, return a singleton list containing prefix.
- *
- * If pathspec and prefix are both empty, return an empty list.
- *
- * This is typically used by built-in commands such as add.c, in order
- * to normalize argv arguments provided to the built-in into a list of
- * paths to process, all relative to the root of the working tree.
- */
-const char **get_pathspec(const char *prefix, const char **pathspec)
-{
-	struct pathspec ps;
-	parse_pathspec(&ps,
-		       PATHSPEC_ALL_MAGIC &
-		       ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
-		       PATHSPEC_PREFER_CWD,
-		       prefix, pathspec);
-	return ps._raw;
-}
-
 void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
 {
 	*dst = *src;
-- 
2.5.0.2.g6ffee06.dirty

^ permalink raw reply related	[relevance 5%]

* Re: [RFC/PATCH 2/2] Testing the new code
  2015-08-03 16:23  2%     ` Stefan Beller
@ 2015-08-03 19:47  2%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-08-03 19:47 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git@vger.kernel.org, Jens Lehmann, Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

> On Fri, Jul 31, 2015 at 6:02 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Stefan Beller <sbeller@google.com> writes:
>>
>>> -module_list()
>>> +module_list_shell()
>>>  {
>>>       eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
>>>       (
>>> @@ -187,6 +187,29 @@ module_list()
>>>       '
>>>  }
>>>
>>> +module_list()
>>> +{
>>> +     # call both the old and new code
>>> +     module_list_shell $@ >/u/git_submodule_module_list_shell 2>/u/git_submodule_module_list_shell2
>>> +     git submodule--helper --module_list $@ >/u/git_submodule_module_list 2>/u/git_submodule_module_list2
>>
>> You seem to be discarding the double-quote around $@ in both of
>> these two places.  Intended?
>
> No, not at all. This was a bit sloppy.

OK.

> This patch was rather showing off how I intend to test the previous patch.

Yeah, I can see what the code is doing, and you already saw that I
didn't disagree with the approach ;).  During a reimplementation
exercise, it often is a good idea, if the code structure allows you
to, to run both implementations and compare the results---but it can
go only so far.  It obviously is tricky to apply the trick to an
operation that is not idempotent to let two implementations to do it
twice in different ways and make sure they produce the same result.

^ permalink raw reply	[relevance 2%]

* Re: [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper
  2015-08-01  1:01  7%   ` Junio C Hamano
@ 2015-08-03 21:30  7%     ` Stefan Beller
  2015-08-03 21:38  6%       ` Junio C Hamano
                         ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Stefan Beller @ 2015-08-03 21:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org, Jens Lehmann, Heiko Voigt

On Fri, Jul 31, 2015 at 6:01 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> +static const char * const git_submodule_helper_usage[] = {
>> +     N_("git submodule--helper --module_list [<path>...]"),
>
> Yuck.  Please do not force --multi_word_opt upon us, which is simply
> too ugly to live around here.  --module-list is perhaps OK,

I agree there. The way you word it here, it sounds as if the mixture
of dashes and underscores are a problem.

> but
> because submodule--helper would not have an default action, I'd
> prefer to make these just "command words", i.e.
>
>     $ git submodule--helper module_list

Why would you use an underscore in here as opposed to a dash?
     $ git submodule--helper module-list

I went with --module-list for now as I see no reason real to make it
a command word for now as it is not user facing but just a helper.
I have a patch from my previous attempt to rewrite "git submodule"
as a whole to accept both command words as well as double dashed
selected modes.

>
>> +int module_list(int argc, const char **argv, const char *prefix)
>> +{
>> +     int i;
>> +     static struct pathspec pathspec;
>> +     const struct cache_entry **ce_entries = NULL;
>> +     int alloc = 0, used = 0;
>> +     char *ps_matched = NULL;
>> +     char *max_prefix;
>> +     int max_prefix_len;
>> +     struct string_list already_printed = STRING_LIST_INIT_NODUP;
>> +
>> +     parse_pathspec(&pathspec, 0,
>> +                    PATHSPEC_PREFER_FULL,
>> +                    prefix, argv);
>> +
>> +     /* Find common prefix for all pathspec's */
>> +     max_prefix = common_prefix(&pathspec);
>> +     max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
>> +
>> +     if (pathspec.nr)
>> +             ps_matched = xcalloc(1, pathspec.nr);
>
> Up to this point it interprets its input, and ...
>
>> +     if (read_cache() < 0)
>> +             die("index file corrupt");
>> +
>> +     for (i = 0; i < active_nr; i++) {
>> +             const struct cache_entry *ce = active_cache[i];
>> +
>> +             if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
>> +                                 max_prefix_len, ps_matched,
>> +                                 S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode)))
>> +                     continue;
>> +
>> +             if (S_ISGITLINK(ce->ce_mode)) {
>> +                     ALLOC_GROW(ce_entries, used + 1, alloc);
>> +                     ce_entries[used++] = ce;
>> +             }
>> +     }
>> +
>> +     if (ps_matched && report_path_error(ps_matched, &pathspec, prefix)) {
>> +             printf("#unmatched\n");
>> +             return 1;
>> +     }
>
> ... does the computation, with diagnosis.
>
> And then it does the I/O with formatting.
>
>> +
>> +     for (i = 0; i < used; i++) {
>> +             const struct cache_entry *ce = ce_entries[i];
> ...
>> +     return 0;
>> +}
>
> When you have the implementation of "foreach-parallel" to move the
> most expensive part of "submodule update" of a tree with 500
> submodules, you would want to receive more or less the same "args"
> as this thing takes and pass the ce_entries[] list to the "spawn and
> run the user script in them in parallel" engine.

That's true, I thought about splitting it up later when I actually need it.
[That seems easier to write, but not easier to review :( ]
I did split up the function just now.

>
> So I think it makes more sense to split this function into two (or
> three).  One that reads from (argc, argv) and allocates and fills
> ce_entries[] can become a helper that you can reuse later.
>
> 'int module_list()' (shouldn't it be static?), can make a call to
> that helper at the begining of it, and the remainder of the function
> would do the textual I/O.

^ permalink raw reply	[relevance 7%]

* Re: [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper
  2015-08-03 21:30  7%     ` Stefan Beller
@ 2015-08-03 21:38  6%       ` Junio C Hamano
  2015-08-03 21:58 18%       ` [PATCH] " Stefan Beller
  2015-08-03 22:04  6%       ` [RFC/PATCH 1/2] " Junio C Hamano
  2 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-08-03 21:38 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git@vger.kernel.org, Jens Lehmann, Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

>>     $ git submodule--helper module_list
>
> Why would you use an underscore in here as opposed to a dash?

Simply because the diff would be easier to read; the callers used to
call module_list shell function, now they call the subcommand with the
same name of submodule--helper.

^ permalink raw reply	[relevance 6%]

* [PATCH] submodule: implement `module_list` as a builtin helper
  2015-08-03 21:30  7%     ` Stefan Beller
  2015-08-03 21:38  6%       ` Junio C Hamano
@ 2015-08-03 21:58 18%       ` Stefan Beller
  2015-08-03 22:04  6%       ` [RFC/PATCH 1/2] " Junio C Hamano
  2 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-03 21:58 UTC (permalink / raw)
  To: gitster; +Cc: git, jens.lehmann, hvoigt, Stefan Beller

Most of the submodule operations work on a set of submodules.
Calculating and using this set is usually done via:

       module_list "$@" | {
           while read mode sha1 stage sm_path
           do
                # the actual operation
           done
       }

Currently the function `module_list` is implemented in the
git-submodule.sh as a shell script wrapping a perl script.
The rewrite is in C, such that it is faster and can later be
easily adapted when other functions are rewritten in C.

git-submodule.sh similar to the builtin commands will navigate
to the top most directory of the repository and keeping the
subdirectories as a variable. As the helper is called from
within the git-submodule.sh script, we are already navigated
to the root level, but the path arguments are stil relative
to the subdirectory we were in when calling git-submodule.sh.
That's why there is a `--prefix` option pointing to an alternative
path where to anchor relative path arguments.

Signed-off-by: Stefan Beller <sbeller@google.com>
---

This doesn't have the `module_list` subcommand word,
but rather uses the `--module-list` mode for now.

However this is not an RFC any more, but I consider it stable.

Thanks,
Stefan

 Makefile                    |   1 +
 builtin.h                   |   1 +
 builtin/submodule--helper.c | 119 ++++++++++++++++++++++++++++++++++++++++++++
 git-submodule.sh            |  54 +++-----------------
 git.c                       |   1 +
 5 files changed, 128 insertions(+), 48 deletions(-)
 create mode 100644 builtin/submodule--helper.c

diff --git a/Makefile b/Makefile
index 8c3c724..6fb7484 100644
--- a/Makefile
+++ b/Makefile
@@ -898,6 +898,7 @@ BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
 BUILTIN_OBJS += builtin/stripspace.o
+BUILTIN_OBJS += builtin/submodule--helper.o
 BUILTIN_OBJS += builtin/symbolic-ref.o
 BUILTIN_OBJS += builtin/tag.o
 BUILTIN_OBJS += builtin/unpack-file.o
diff --git a/builtin.h b/builtin.h
index 9e04f97..7bf9597 100644
--- a/builtin.h
+++ b/builtin.h
@@ -118,6 +118,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
 extern int cmd_status(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
+extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_tag(int argc, const char **argv, const char *prefix);
 extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
new file mode 100644
index 0000000..3f6d07d
--- /dev/null
+++ b/builtin/submodule--helper.c
@@ -0,0 +1,119 @@
+#include "builtin.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "quote.h"
+#include "pathspec.h"
+#include "dir.h"
+#include "utf8.h"
+
+static const char * const git_submodule_helper_usage[] = {
+	N_("git submodule--helper [<options>] [<path>...]"),
+	NULL
+};
+
+static char *ps_matched;
+static int max_prefix_len;
+static const struct cache_entry **ce_entries;
+static int ce_alloc, ce_used;
+static const char *alternative_path;
+
+static void module_list_compute(int argc, const char **argv,
+				const char *prefix,
+				struct pathspec *pathspec)
+{
+	int i;
+	char *max_prefix;
+	parse_pathspec(pathspec, 0,
+		       PATHSPEC_PREFER_FULL |
+		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
+		       prefix, argv);
+
+	/* Find common prefix for all pathspec's */
+	max_prefix = common_prefix(pathspec);
+	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
+
+	if (pathspec->nr)
+		ps_matched = xcalloc(1, pathspec->nr);
+
+
+	if (read_cache() < 0)
+		die("index file corrupt");
+
+	for (i = 0; i < active_nr; i++) {
+		const struct cache_entry *ce = active_cache[i];
+
+		if (!match_pathspec(pathspec, ce->name, ce_namelen(ce),
+				    max_prefix_len, ps_matched,
+				    S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode)))
+			continue;
+
+		if (S_ISGITLINK(ce->ce_mode)) {
+			ALLOC_GROW(ce_entries, ce_used + 1, ce_alloc);
+			ce_entries[ce_used++] = ce;
+		}
+	}
+}
+
+static int module_list(int argc, const char **argv, const char *prefix)
+{
+	int i;
+	struct string_list already_printed = STRING_LIST_INIT_NODUP;
+	struct pathspec pathspec;
+
+	module_list_compute(argc, argv, prefix, &pathspec);
+
+	if (ps_matched && report_path_error(ps_matched, &pathspec, prefix)) {
+		printf("#unmatched\n");
+		return 1;
+	}
+
+	for (i = 0; i < ce_used; i++) {
+		const struct cache_entry *ce = ce_entries[i];
+
+		if (string_list_has_string(&already_printed, ce->name))
+			continue;
+
+		if (ce_stage(ce)) {
+			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
+		} else {
+			printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce));
+		}
+
+		utf8_fprintf(stdout, "%s\n", ce->name);
+
+		string_list_insert(&already_printed, ce->name);
+	}
+	return 0;
+}
+
+int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
+{
+	enum {
+		MODE_UNSPECIFIED = 0,
+		MODE_MODULE_LIST,
+	} cmdmode = MODE_UNSPECIFIED;
+
+	struct option options[] = {
+		OPT_CMDMODE(0, "module-list", &cmdmode,
+			    N_("Get the submodule list"), MODE_MODULE_LIST),
+		OPT_STRING(0, "prefix", &alternative_path,
+			   N_("path"),
+			   N_("alternative anchor for relative paths")),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options,
+			     git_submodule_helper_usage, 0);
+
+	switch (cmdmode) {
+	case MODE_MODULE_LIST:
+		return module_list(argc, argv, alternative_path
+					       ? alternative_path
+					       : prefix);
+		break;
+	case MODE_UNSPECIFIED:
+		usage_with_options(git_submodule_helper_usage, options);
+		break;
+	}
+	return 0;
+}
diff --git a/git-submodule.sh b/git-submodule.sh
index 36797c3..e0ab06e 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,48 +145,6 @@ relative_path ()
 	echo "$result$target"
 }
 
-#
-# Get submodule info for registered submodules
-# $@ = path to limit submodule list
-#
-module_list()
-{
-	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
-	(
-		git ls-files -z --error-unmatch --stage -- "$@" ||
-		echo "unmatched pathspec exists"
-	) |
-	@@PERL@@ -e '
-	my %unmerged = ();
-	my ($null_sha1) = ("0" x 40);
-	my @out = ();
-	my $unmatched = 0;
-	$/ = "\0";
-	while (<STDIN>) {
-		if (/^unmatched pathspec/) {
-			$unmatched = 1;
-			next;
-		}
-		chomp;
-		my ($mode, $sha1, $stage, $path) =
-			/^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
-		next unless $mode eq "160000";
-		if ($stage ne "0") {
-			if (!$unmerged{$path}++) {
-				push @out, "$mode $null_sha1 U\t$path\n";
-			}
-			next;
-		}
-		push @out, "$_\n";
-	}
-	if ($unmatched) {
-		print "#unmatched\n";
-	} else {
-		print for (@out);
-	}
-	'
-}
-
 die_if_unmatched ()
 {
 	if test "$1" = "#unmatched"
@@ -532,7 +490,7 @@ cmd_foreach()
 	# command in the subshell (and a recursive call to this function)
 	exec 3<&0
 
-	module_list |
+	git submodule--helper --prefix "$wt_prefix" --module-list |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -592,7 +550,7 @@ cmd_init()
 		shift
 	done
 
-	module_list "$@" |
+	git submodule--helper --prefix "$wt_prefix" --module-list "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -674,7 +632,7 @@ cmd_deinit()
 		die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
 	fi
 
-	module_list "$@" |
+	git submodule--helper --prefix "$wt_prefix" --module-list "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -790,7 +748,7 @@ cmd_update()
 	fi
 
 	cloned_modules=
-	module_list "$@" | {
+	git submodule--helper --prefix "$wt_prefix" --module-list "$@" | {
 	err=
 	while read mode sha1 stage sm_path
 	do
@@ -1222,7 +1180,7 @@ cmd_status()
 		shift
 	done
 
-	module_list "$@" |
+	git submodule--helper --prefix "$wt_prefix" --module-list "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -1299,7 +1257,7 @@ cmd_sync()
 		esac
 	done
 	cd_to_toplevel
-	module_list "$@" |
+	git submodule--helper --prefix "$wt_prefix" --module-list "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
diff --git a/git.c b/git.c
index fe94066..721995e 100644
--- a/git.c
+++ b/git.c
@@ -468,6 +468,7 @@ static struct cmd_struct commands[] = {
 	{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 	{ "stripspace", cmd_stripspace },
+	{ "submodule--helper", cmd_submodule__helper, RUN_SETUP },
 	{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
 	{ "tag", cmd_tag, RUN_SETUP },
 	{ "unpack-file", cmd_unpack_file, RUN_SETUP },
-- 
2.5.0.5.gffc0ba2.dirty

^ permalink raw reply related	[relevance 18%]

* Re: [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper
  2015-08-03 21:30  7%     ` Stefan Beller
  2015-08-03 21:38  6%       ` Junio C Hamano
  2015-08-03 21:58 18%       ` [PATCH] " Stefan Beller
@ 2015-08-03 22:04  6%       ` Junio C Hamano
  2015-08-03 22:13  4%         ` Stefan Beller
  2015-08-03 22:58 19%         ` [PATCH] " Stefan Beller
  2 siblings, 2 replies; 200+ results
From: Junio C Hamano @ 2015-08-03 22:04 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git@vger.kernel.org, Jens Lehmann, Heiko Voigt

Stefan Beller <sbeller@google.com> writes:

> On Fri, Jul 31, 2015 at 6:01 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Stefan Beller <sbeller@google.com> writes:
>>
>>> +static const char * const git_submodule_helper_usage[] = {
>>> +     N_("git submodule--helper --module_list [<path>...]"),
>>
>> Yuck.  Please do not force --multi_word_opt upon us, which is simply
>> too ugly to live around here.  --module-list is perhaps OK,
>
> I agree there. The way you word it here, it sounds as if the mixture
> of dashes and underscores are a problem.
>
>> but
>> because submodule--helper would not have an default action, I'd
>> prefer to make these just "command words", i.e.
>>
>>     $ git submodule--helper module_list
>
> Why would you use an underscore in here as opposed to a dash?
>      $ git submodule--helper module-list
>
> I went with --module-list for now as I see no reason real to make it
> a command word for now ...

The biggest reason why we should not add more --command-mode is to
avoid confusion (and copy & paste misdesign by others).  If you use
the command-word interface, it is crystal clear that

 (1) the word 'module_list' must be the first token after the
     subcommand name, no need to parse "subcmd --opt --cmd", and
     mislead the users to think incorrectly that ...

 (2) ... "cmd --optA --cmd1 --optB --cmd2" might be allowed, which
     would lead you to add code to reject, saying "cmd1 and cmd2 are
     incompatible".

So I'd prefer to see it fixed before you start supporting more
commands in submodule--helper.  It will need unnecessary patch noise
to fix it later.

^ permalink raw reply	[relevance 6%]

* Re: [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper
  2015-08-03 22:04  6%       ` [RFC/PATCH 1/2] " Junio C Hamano
@ 2015-08-03 22:13  4%         ` Stefan Beller
  2015-08-03 22:58 19%         ` [PATCH] " Stefan Beller
  1 sibling, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-03 22:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org, Jens Lehmann, Heiko Voigt

On Mon, Aug 3, 2015 at 3:04 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> On Fri, Jul 31, 2015 at 6:01 PM, Junio C Hamano <gitster@pobox.com> wrote:
>>> Stefan Beller <sbeller@google.com> writes:
>>>
>>>> +static const char * const git_submodule_helper_usage[] = {
>>>> +     N_("git submodule--helper --module_list [<path>...]"),
>>>
>>> Yuck.  Please do not force --multi_word_opt upon us, which is simply
>>> too ugly to live around here.  --module-list is perhaps OK,
>>
>> I agree there. The way you word it here, it sounds as if the mixture
>> of dashes and underscores are a problem.
>>
>>> but
>>> because submodule--helper would not have an default action, I'd
>>> prefer to make these just "command words", i.e.
>>>
>>>     $ git submodule--helper module_list
>>
>> Why would you use an underscore in here as opposed to a dash?
>>      $ git submodule--helper module-list
>>
>> I went with --module-list for now as I see no reason real to make it
>> a command word for now ...
>
> The biggest reason why we should not add more --command-mode is to
> avoid confusion (and copy & paste misdesign by others).  If you use
> the command-word interface, it is crystal clear that
>
>  (1) the word 'module_list' must be the first token after the
>      subcommand name, no need to parse "subcmd --opt --cmd", and
>      mislead the users to think incorrectly that ...
>
>  (2) ... "cmd --optA --cmd1 --optB --cmd2" might be allowed, which
>      would lead you to add code to reject, saying "cmd1 and cmd2 are
>      incompatible".
>
> So I'd prefer to see it fixed before you start supporting more
> commands in submodule--helper.  It will need unnecessary patch noise
> to fix it later.

So we had this discussion some time ago [1] and my understanding from back
then was to rather have --command-mode instead of subcommand words because
that's what most git commands use nowadays, so we don't want to add more
of the competing style. It's also easier to work with as we have a powerful
option parsing implementation.

It seems your opinion has swayed. I'll change it then.

[1] $gmane/254076 or $gmane/231376/focus=231478

^ permalink raw reply	[relevance 4%]

* [PATCH] submodule: implement `module_list` as a builtin helper
  2015-08-03 22:04  6%       ` [RFC/PATCH 1/2] " Junio C Hamano
  2015-08-03 22:13  4%         ` Stefan Beller
@ 2015-08-03 22:58 19%         ` Stefan Beller
  1 sibling, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-03 22:58 UTC (permalink / raw)
  To: gitster; +Cc: git, jens.lehmann, hvoigt, Stefan Beller

Most of the submodule operations work on a set of submodules.
Calculating and using this set is usually done via:

       module_list "$@" | {
           while read mode sha1 stage sm_path
           do
                # the actual operation
           done
       }

Currently the function `module_list` is implemented in the
git-submodule.sh as a shell script wrapping a perl script.
The rewrite is in C, such that it is faster and can later be
easily adapted when other functions are rewritten in C.

git-submodule.sh similar to the builtin commands will navigate
to the top most directory of the repository and keeping the
subdirectories as a variable. As the helper is called from
within the git-submodule.sh script, we are already navigated
to the root level, but the path arguments are stil relative
to the subdirectory we were in when calling git-submodule.sh.
That's why there is a `--prefix` option pointing to an alternative
path where to anchor relative path arguments.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Makefile                    |   1 +
 builtin.h                   |   1 +
 builtin/submodule--helper.c | 110 ++++++++++++++++++++++++++++++++++++++++++++
 git-submodule.sh            |  54 +++-------------------
 git.c                       |   1 +
 5 files changed, 119 insertions(+), 48 deletions(-)
 create mode 100644 builtin/submodule--helper.c

diff --git a/Makefile b/Makefile
index 8c3c724..6fb7484 100644
--- a/Makefile
+++ b/Makefile
@@ -898,6 +898,7 @@ BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
 BUILTIN_OBJS += builtin/stripspace.o
+BUILTIN_OBJS += builtin/submodule--helper.o
 BUILTIN_OBJS += builtin/symbolic-ref.o
 BUILTIN_OBJS += builtin/tag.o
 BUILTIN_OBJS += builtin/unpack-file.o
diff --git a/builtin.h b/builtin.h
index 9e04f97..7bf9597 100644
--- a/builtin.h
+++ b/builtin.h
@@ -118,6 +118,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
 extern int cmd_status(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
+extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_tag(int argc, const char **argv, const char *prefix);
 extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
new file mode 100644
index 0000000..fbd9568
--- /dev/null
+++ b/builtin/submodule--helper.c
@@ -0,0 +1,110 @@
+#include "builtin.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "quote.h"
+#include "pathspec.h"
+#include "dir.h"
+#include "utf8.h"
+
+static char *ps_matched;
+static const struct cache_entry **ce_entries;
+static int ce_alloc, ce_used;
+
+static void module_list_compute(int argc, const char **argv,
+				const char *prefix,
+				struct pathspec *pathspec)
+{
+	int i;
+	char *max_prefix;
+	int max_prefix_len;
+	parse_pathspec(pathspec, 0,
+		       PATHSPEC_PREFER_FULL |
+		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
+		       prefix, argv);
+
+	/* Find common prefix for all pathspec's */
+	max_prefix = common_prefix(pathspec);
+	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
+
+	if (pathspec->nr)
+		ps_matched = xcalloc(1, pathspec->nr);
+
+
+	if (read_cache() < 0)
+		die("index file corrupt");
+
+	for (i = 0; i < active_nr; i++) {
+		const struct cache_entry *ce = active_cache[i];
+
+		if (!match_pathspec(pathspec, ce->name, ce_namelen(ce),
+				    max_prefix_len, ps_matched,
+				    S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode)))
+			continue;
+
+		if (S_ISGITLINK(ce->ce_mode)) {
+			ALLOC_GROW(ce_entries, ce_used + 1, ce_alloc);
+			ce_entries[ce_used++] = ce;
+		}
+	}
+}
+
+static int module_list(int argc, const char **argv, const char *prefix)
+{
+	int i;
+	struct string_list already_printed = STRING_LIST_INIT_NODUP;
+	struct pathspec pathspec;
+	const char *alternative_path;
+
+	struct option module_list_options[] = {
+		OPT_STRING(0, "prefix", &alternative_path,
+			   N_("path"),
+			   N_("alternative anchor for relative paths")),
+		OPT_END()
+	};
+
+	static const char * const git_submodule_helper_usage[] = {
+		N_("git submodule--helper module_list [--prefix=<path>] [<path>...]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, module_list_options,
+			     git_submodule_helper_usage, 0);
+
+	module_list_compute(argc, argv, alternative_path
+					? alternative_path
+					: prefix, &pathspec);
+
+	if (ps_matched && report_path_error(ps_matched, &pathspec, prefix)) {
+		printf("#unmatched\n");
+		return 1;
+	}
+
+	for (i = 0; i < ce_used; i++) {
+		const struct cache_entry *ce = ce_entries[i];
+
+		if (string_list_has_string(&already_printed, ce->name))
+			continue;
+
+		if (ce_stage(ce)) {
+			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
+		} else {
+			printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce));
+		}
+
+		utf8_fprintf(stdout, "%s\n", ce->name);
+
+		string_list_insert(&already_printed, ce->name);
+	}
+	return 0;
+}
+
+int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
+{
+	if (argc < 2)
+		goto usage;
+
+	if (!strcmp(argv[1], "module_list"))
+		return module_list(--argc, ++argv, prefix);
+usage:
+	usage("git submodule--helper module_list\n");
+}
diff --git a/git-submodule.sh b/git-submodule.sh
index 36797c3..af9ecef 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,48 +145,6 @@ relative_path ()
 	echo "$result$target"
 }
 
-#
-# Get submodule info for registered submodules
-# $@ = path to limit submodule list
-#
-module_list()
-{
-	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
-	(
-		git ls-files -z --error-unmatch --stage -- "$@" ||
-		echo "unmatched pathspec exists"
-	) |
-	@@PERL@@ -e '
-	my %unmerged = ();
-	my ($null_sha1) = ("0" x 40);
-	my @out = ();
-	my $unmatched = 0;
-	$/ = "\0";
-	while (<STDIN>) {
-		if (/^unmatched pathspec/) {
-			$unmatched = 1;
-			next;
-		}
-		chomp;
-		my ($mode, $sha1, $stage, $path) =
-			/^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
-		next unless $mode eq "160000";
-		if ($stage ne "0") {
-			if (!$unmerged{$path}++) {
-				push @out, "$mode $null_sha1 U\t$path\n";
-			}
-			next;
-		}
-		push @out, "$_\n";
-	}
-	if ($unmatched) {
-		print "#unmatched\n";
-	} else {
-		print for (@out);
-	}
-	'
-}
-
 die_if_unmatched ()
 {
 	if test "$1" = "#unmatched"
@@ -532,7 +490,7 @@ cmd_foreach()
 	# command in the subshell (and a recursive call to this function)
 	exec 3<&0
 
-	module_list |
+	git submodule--helper module_list --prefix "$wt_prefix"|
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -592,7 +550,7 @@ cmd_init()
 		shift
 	done
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -674,7 +632,7 @@ cmd_deinit()
 		die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
 	fi
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -790,7 +748,7 @@ cmd_update()
 	fi
 
 	cloned_modules=
-	module_list "$@" | {
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" | {
 	err=
 	while read mode sha1 stage sm_path
 	do
@@ -1222,7 +1180,7 @@ cmd_status()
 		shift
 	done
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -1299,7 +1257,7 @@ cmd_sync()
 		esac
 	done
 	cd_to_toplevel
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
diff --git a/git.c b/git.c
index fe94066..721995e 100644
--- a/git.c
+++ b/git.c
@@ -468,6 +468,7 @@ static struct cmd_struct commands[] = {
 	{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 	{ "stripspace", cmd_stripspace },
+	{ "submodule--helper", cmd_submodule__helper, RUN_SETUP },
 	{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
 	{ "tag", cmd_tag, RUN_SETUP },
 	{ "unpack-file", cmd_unpack_file, RUN_SETUP },
-- 
2.5.0.1.gc648038.dirty

^ permalink raw reply related	[relevance 19%]

* [PATCH 1/4] submodule: implement `module_list` as a builtin helper
@ 2015-08-05  0:04 19% Stefan Beller
  2015-08-05  0:04 23% ` [PATCH 2/4] submodule: implement `module_name` " Stefan Beller
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Stefan Beller @ 2015-08-05  0:04 UTC (permalink / raw)
  To: gitster; +Cc: git, jens.lehmann, hvoigt, Stefan Beller

Most of the submodule operations work on a set of submodules.
Calculating and using this set is usually done via:

       module_list "$@" | {
           while read mode sha1 stage sm_path
           do
                # the actual operation
           done
       }

Currently the function `module_list` is implemented in the
git-submodule.sh as a shell script wrapping a perl script.
The rewrite is in C, such that it is faster and can later be
easily adapted when other functions are rewritten in C.

git-submodule.sh similar to the builtin commands will navigate
to the top most directory of the repository and keeping the
subdirectories as a variable. As the helper is called from
within the git-submodule.sh script, we are already navigated
to the root level, but the path arguments are stil relative
to the subdirectory we were in when calling git-submodule.sh.
That's why there is a `--prefix` option pointing to an alternative
path where to anchor relative path arguments.

Signed-off-by: Stefan Beller <sbeller@google.com>
---

The same as yesterday evening, just an entry added to .gitignore.

So we'll have a "git submodule--helper module_list" here.

 .gitignore                  |   1 +
 Makefile                    |   1 +
 builtin.h                   |   1 +
 builtin/submodule--helper.c | 111 ++++++++++++++++++++++++++++++++++++++++++++
 git-submodule.sh            |  54 +++------------------
 git.c                       |   1 +
 6 files changed, 121 insertions(+), 48 deletions(-)
 create mode 100644 builtin/submodule--helper.c

diff --git a/.gitignore b/.gitignore
index a685ec1..2a69ba0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -155,6 +155,7 @@
 /git-status
 /git-stripspace
 /git-submodule
+/git-submodule--helper
 /git-svn
 /git-symbolic-ref
 /git-tag
diff --git a/Makefile b/Makefile
index 7efedbe..460d17a 100644
--- a/Makefile
+++ b/Makefile
@@ -899,6 +899,7 @@ BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
 BUILTIN_OBJS += builtin/stripspace.o
+BUILTIN_OBJS += builtin/submodule--helper.o
 BUILTIN_OBJS += builtin/symbolic-ref.o
 BUILTIN_OBJS += builtin/tag.o
 BUILTIN_OBJS += builtin/unpack-file.o
diff --git a/builtin.h b/builtin.h
index 839483d..924e6c4 100644
--- a/builtin.h
+++ b/builtin.h
@@ -119,6 +119,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
 extern int cmd_status(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
+extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_tag(int argc, const char **argv, const char *prefix);
 extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
new file mode 100644
index 0000000..cb18ddf
--- /dev/null
+++ b/builtin/submodule--helper.c
@@ -0,0 +1,111 @@
+#include "builtin.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "quote.h"
+#include "pathspec.h"
+#include "dir.h"
+#include "utf8.h"
+
+static char *ps_matched;
+static const struct cache_entry **ce_entries;
+static int ce_alloc, ce_used;
+static struct pathspec pathspec;
+static const char *alternative_path;
+
+static void module_list_compute(int argc, const char **argv,
+				const char *prefix,
+				struct pathspec *pathspec)
+{
+	int i;
+	char *max_prefix;
+	int max_prefix_len;
+	parse_pathspec(pathspec, 0,
+		       PATHSPEC_PREFER_FULL |
+		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
+		       prefix, argv);
+
+	/* Find common prefix for all pathspec's */
+	max_prefix = common_prefix(pathspec);
+	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
+
+	if (pathspec->nr)
+		ps_matched = xcalloc(1, pathspec->nr);
+
+
+	if (read_cache() < 0)
+		die("index file corrupt");
+
+	for (i = 0; i < active_nr; i++) {
+		const struct cache_entry *ce = active_cache[i];
+
+		if (!match_pathspec(pathspec, ce->name, ce_namelen(ce),
+				    max_prefix_len, ps_matched,
+				    S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode)))
+			continue;
+
+		if (S_ISGITLINK(ce->ce_mode)) {
+			ALLOC_GROW(ce_entries, ce_used + 1, ce_alloc);
+			ce_entries[ce_used++] = ce;
+		}
+	}
+}
+
+static int module_list(int argc, const char **argv, const char *prefix)
+{
+	int i;
+	struct string_list already_printed = STRING_LIST_INIT_NODUP;
+
+	struct option module_list_options[] = {
+		OPT_STRING(0, "prefix", &alternative_path,
+			   N_("path"),
+			   N_("alternative anchor for relative paths")),
+		OPT_END()
+	};
+
+	static const char * const git_submodule_helper_usage[] = {
+		N_("git submodule--helper module_list [--prefix=<path>] [<path>...]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, module_list_options,
+			     git_submodule_helper_usage, 0);
+
+	module_list_compute(argc, argv, alternative_path
+					? alternative_path
+					: prefix, &pathspec);
+
+	if (ps_matched && report_path_error(ps_matched, &pathspec, prefix)) {
+		printf("#unmatched\n");
+		return 1;
+	}
+
+	for (i = 0; i < ce_used; i++) {
+		const struct cache_entry *ce = ce_entries[i];
+
+		if (string_list_has_string(&already_printed, ce->name))
+			continue;
+
+		if (ce_stage(ce)) {
+			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
+		} else {
+			printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce));
+		}
+
+		utf8_fprintf(stdout, "%s\n", ce->name);
+
+		string_list_insert(&already_printed, ce->name);
+	}
+	return 0;
+}
+
+int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
+{
+	if (argc < 2)
+		goto usage;
+
+	if (!strcmp(argv[1], "module_list"))
+		return module_list(argc - 1, argv + 1, prefix);
+
+usage:
+	usage("git submodule--helper module_list\n");
+}
diff --git a/git-submodule.sh b/git-submodule.sh
index 36797c3..af9ecef 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,48 +145,6 @@ relative_path ()
 	echo "$result$target"
 }
 
-#
-# Get submodule info for registered submodules
-# $@ = path to limit submodule list
-#
-module_list()
-{
-	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
-	(
-		git ls-files -z --error-unmatch --stage -- "$@" ||
-		echo "unmatched pathspec exists"
-	) |
-	@@PERL@@ -e '
-	my %unmerged = ();
-	my ($null_sha1) = ("0" x 40);
-	my @out = ();
-	my $unmatched = 0;
-	$/ = "\0";
-	while (<STDIN>) {
-		if (/^unmatched pathspec/) {
-			$unmatched = 1;
-			next;
-		}
-		chomp;
-		my ($mode, $sha1, $stage, $path) =
-			/^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
-		next unless $mode eq "160000";
-		if ($stage ne "0") {
-			if (!$unmerged{$path}++) {
-				push @out, "$mode $null_sha1 U\t$path\n";
-			}
-			next;
-		}
-		push @out, "$_\n";
-	}
-	if ($unmatched) {
-		print "#unmatched\n";
-	} else {
-		print for (@out);
-	}
-	'
-}
-
 die_if_unmatched ()
 {
 	if test "$1" = "#unmatched"
@@ -532,7 +490,7 @@ cmd_foreach()
 	# command in the subshell (and a recursive call to this function)
 	exec 3<&0
 
-	module_list |
+	git submodule--helper module_list --prefix "$wt_prefix"|
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -592,7 +550,7 @@ cmd_init()
 		shift
 	done
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -674,7 +632,7 @@ cmd_deinit()
 		die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
 	fi
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -790,7 +748,7 @@ cmd_update()
 	fi
 
 	cloned_modules=
-	module_list "$@" | {
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" | {
 	err=
 	while read mode sha1 stage sm_path
 	do
@@ -1222,7 +1180,7 @@ cmd_status()
 		shift
 	done
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -1299,7 +1257,7 @@ cmd_sync()
 		esac
 	done
 	cd_to_toplevel
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
diff --git a/git.c b/git.c
index 55c327c..deecba0 100644
--- a/git.c
+++ b/git.c
@@ -469,6 +469,7 @@ static struct cmd_struct commands[] = {
 	{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 	{ "stripspace", cmd_stripspace },
+	{ "submodule--helper", cmd_submodule__helper, RUN_SETUP },
 	{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
 	{ "tag", cmd_tag, RUN_SETUP },
 	{ "unpack-file", cmd_unpack_file, RUN_SETUP },
-- 
2.5.0.2.gbb9888f.dirty

^ permalink raw reply related	[relevance 19%]

* [PATCH 2/4] submodule: implement `module_name` as a builtin helper
  2015-08-05  0:04 19% [PATCH 1/4] submodule: implement `module_list` as a builtin helper Stefan Beller
@ 2015-08-05  0:04 23% ` Stefan Beller
  2015-08-05  0:05  4%   ` Stefan Beller
                     ` (2 more replies)
  2015-08-05 18:31  6% ` [PATCH 1/4] submodule: implement `module_list` " Jens Lehmann
  2015-08-07 19:53  4% ` Junio C Hamano
  2 siblings, 3 replies; 200+ results
From: Stefan Beller @ 2015-08-05  0:04 UTC (permalink / raw)
  To: gitster; +Cc: git, jens.lehmann, hvoigt, Stefan Beller

The goal of this series being rewriting `git submodule update`,
we don't want to call out to the shell script for config lookups.

So reimplement the lookup of the submodule name in C.

Signed-off-by: Stefan Beller <sbeller@google.com>
---

 When I started to implement git submodule add in the helper, I realized
 the very first thing to be done would be module_name translated to C,
 so I did that separately. Maybe we need to split this up as well into two
 separate steps for processing and I/O, such that it can be reused better
 from a future "git submodule--helper update" function

 builtin/submodule--helper.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
 git-submodule.sh            | 32 +++++++-----------------------
 2 files changed, 54 insertions(+), 25 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index cb18ddf..dd5635f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -5,6 +5,8 @@
 #include "pathspec.h"
 #include "dir.h"
 #include "utf8.h"
+#include "run-command.h"
+#include "string-list.h"
 
 static char *ps_matched;
 static const struct cache_entry **ce_entries;
@@ -98,6 +100,48 @@ static int module_list(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+
+static int collect_module_names(const char *key, const char *value, void *cb)
+{
+	size_t len;
+	struct string_list *sl = cb;
+
+	if (starts_with(key, "submodule.")
+	    && strip_suffix(key, ".path", &len)) {
+		struct strbuf sb = STRBUF_INIT;
+		strbuf_add(&sb, key + strlen("submodule."),
+				len - strlen("submodule."));
+		string_list_insert(sl, value)->util = strbuf_detach(&sb, NULL);
+		strbuf_release(&sb);
+	}
+
+	return 0;
+}
+
+static int module_name(int argc, const char **argv, const char *prefix)
+{
+	struct string_list_item *item;
+	struct git_config_source config_source;
+	struct string_list values = STRING_LIST_INIT_DUP;
+
+	if (!argc)
+		usage("git submodule--helper module_name <path>\n");
+
+	memset(&config_source, 0, sizeof(config_source));
+	config_source.file = ".gitmodules";
+
+	if (git_config_with_options(collect_module_names, &values,
+				    &config_source, 1) < 0)
+		die(_("unknown error occured while reading the git modules file"));
+
+	item = string_list_lookup(&values, argv[0]);
+	if (item)
+		printf("%s\n", (char*)item->util);
+	else
+		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
+	return 0;
+}
+
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 {
 	if (argc < 2)
@@ -106,6 +150,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 	if (!strcmp(argv[1], "module_list"))
 		return module_list(argc - 1, argv + 1, prefix);
 
+	if (!strcmp(argv[1], "module_name"))
+		return module_name(argc - 2, argv + 2, prefix);
+
 usage:
 	usage("git submodule--helper module_list\n");
 }
diff --git a/git-submodule.sh b/git-submodule.sh
index af9ecef..e6ff38d 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -178,24 +178,6 @@ get_submodule_config () {
 	printf '%s' "${value:-$default}"
 }
 
-
-#
-# Map submodule path to submodule name
-#
-# $1 = path
-#
-module_name()
-{
-	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
-	sm_path="$1"
-	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
-	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
-		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
-	test -z "$name" &&
-	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
-	printf '%s\n' "$name"
-}
-
 #
 # Clone a submodule
 #
@@ -498,7 +480,7 @@ cmd_foreach()
 		then
 			displaypath=$(relative_path "$sm_path")
 			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
-			name=$(module_name "$sm_path")
+			name=$(git submodule--helper module_name "$sm_path")
 			(
 				prefix="$prefix$sm_path/"
 				clear_local_git_env
@@ -554,7 +536,7 @@ cmd_init()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -636,7 +618,7 @@ cmd_deinit()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -758,7 +740,7 @@ cmd_update()
 			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 			continue
 		fi
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		branch=$(get_submodule_config "$name" branch master)
 		if ! test -z "$update"
@@ -1022,7 +1004,7 @@ cmd_summary() {
 			# Respect the ignore setting for --for-status.
 			if test -n "$for_status"
 			then
-				name=$(module_name "$sm_path")
+				name=$(git submodule--helper module_name "$sm_path")
 				ignore_config=$(get_submodule_config "$name" ignore none)
 				test $status != A && test $ignore_config = all && continue
 			fi
@@ -1184,7 +1166,7 @@ cmd_status()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		displaypath=$(relative_path "$prefix$sm_path")
 		if test "$stage" = U
@@ -1261,7 +1243,7 @@ cmd_sync()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path")
+		name=$(git submodule--helper module_name "$sm_path")
 		url=$(git config -f .gitmodules --get submodule."$name".url)
 
 		# Possibly a url relative to parent
-- 
2.5.0.2.gbb9888f.dirty

^ permalink raw reply related	[relevance 23%]

* Re: [PATCH 2/4] submodule: implement `module_name` as a builtin helper
  2015-08-05  0:04 23% ` [PATCH 2/4] submodule: implement `module_name` " Stefan Beller
@ 2015-08-05  0:05  4%   ` Stefan Beller
  2015-08-05  0:58  4%   ` Eric Sunshine
  2015-08-05 19:06  7%   ` Jens Lehmann
  2 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-05  0:05 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git@vger.kernel.org, Jens Lehmann, Heiko Voigt, Stefan Beller

The series consists of 2 patches only actually. The next patches have
not been sent as they are heavy WIP.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH 2/4] submodule: implement `module_name` as a builtin helper
  2015-08-05  0:04 23% ` [PATCH 2/4] submodule: implement `module_name` " Stefan Beller
  2015-08-05  0:05  4%   ` Stefan Beller
@ 2015-08-05  0:58  4%   ` Eric Sunshine
  2015-08-05 16:29  4%     ` Stefan Beller
  2015-08-05 19:06  7%   ` Jens Lehmann
  2 siblings, 1 reply; 200+ results
From: Eric Sunshine @ 2015-08-05  0:58 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Junio C Hamano, Git List, Jens Lehmann, Heiko Voigt

On Tue, Aug 4, 2015 at 8:04 PM, Stefan Beller <sbeller@google.com> wrote:
> The goal of this series being rewriting `git submodule update`,
> we don't want to call out to the shell script for config lookups.
>
> So reimplement the lookup of the submodule name in C.
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index cb18ddf..dd5635f 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -98,6 +100,48 @@ static int module_list(int argc, const char **argv, const char *prefix)
> +static int collect_module_names(const char *key, const char *value, void *cb)
> +{
> +       size_t len;
> +       struct string_list *sl = cb;
> +
> +       if (starts_with(key, "submodule.")
> +           && strip_suffix(key, ".path", &len)) {
> +               struct strbuf sb = STRBUF_INIT;
> +               strbuf_add(&sb, key + strlen("submodule."),
> +                               len - strlen("submodule."));
> +               string_list_insert(sl, value)->util = strbuf_detach(&sb, NULL);
> +               strbuf_release(&sb);

Why the complexity and overhead of a strbuf when the same could be
accomplished more easily and straightforwardly with xstrndup()?

> +       }
> +
> +       return 0;
> +}
> +
> +static int module_name(int argc, const char **argv, const char *prefix)
> +{
> +       struct string_list_item *item;
> +       struct git_config_source config_source;
> +       struct string_list values = STRING_LIST_INIT_DUP;
> +
> +       if (!argc)

Do you mean?

    if (argc != 1)

> +               usage("git submodule--helper module_name <path>\n");
> +
> +       memset(&config_source, 0, sizeof(config_source));
> +       config_source.file = ".gitmodules";
> +
> +       if (git_config_with_options(collect_module_names, &values,
> +                                   &config_source, 1) < 0)
> +               die(_("unknown error occured while reading the git modules file"));
> +
> +       item = string_list_lookup(&values, argv[0]);
> +       if (item)
> +               printf("%s\n", (char*)item->util);
> +       else
> +               die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
> +       return 0;
> +}
> +
>  int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>  {
>         if (argc < 2)
> @@ -106,6 +150,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>         if (!strcmp(argv[1], "module_list"))
>                 return module_list(argc - 1, argv + 1, prefix);
>
> +       if (!strcmp(argv[1], "module_name"))
> +               return module_name(argc - 2, argv + 2, prefix);
> +
>  usage:
>         usage("git submodule--helper module_list\n");
>  }

^ permalink raw reply	[relevance 4%]

* Re: [PATCH 2/4] submodule: implement `module_name` as a builtin helper
  2015-08-05  0:58  4%   ` Eric Sunshine
@ 2015-08-05 16:29  4%     ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-05 16:29 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: Junio C Hamano, Git List, Jens Lehmann, Heiko Voigt

On Tue, Aug 4, 2015 at 5:58 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:
> On Tue, Aug 4, 2015 at 8:04 PM, Stefan Beller <sbeller@google.com> wrote:
>> The goal of this series being rewriting `git submodule update`,
>> we don't want to call out to the shell script for config lookups.
>>
>> So reimplement the lookup of the submodule name in C.
>>
>> Signed-off-by: Stefan Beller <sbeller@google.com>
>> ---
>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
>> index cb18ddf..dd5635f 100644
>> --- a/builtin/submodule--helper.c
>> +++ b/builtin/submodule--helper.c
>> @@ -98,6 +100,48 @@ static int module_list(int argc, const char **argv, const char *prefix)
>> +static int collect_module_names(const char *key, const char *value, void *cb)
>> +{
>> +       size_t len;
>> +       struct string_list *sl = cb;
>> +
>> +       if (starts_with(key, "submodule.")
>> +           && strip_suffix(key, ".path", &len)) {
>> +               struct strbuf sb = STRBUF_INIT;
>> +               strbuf_add(&sb, key + strlen("submodule."),
>> +                               len - strlen("submodule."));
>> +               string_list_insert(sl, value)->util = strbuf_detach(&sb, NULL);
>> +               strbuf_release(&sb);
>
> Why the complexity and overhead of a strbuf when the same could be
> accomplished more easily and straightforwardly with xstrndup()?

fixed.

>
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int module_name(int argc, const char **argv, const char *prefix)
>> +{
>> +       struct string_list_item *item;
>> +       struct git_config_source config_source;
>> +       struct string_list values = STRING_LIST_INIT_DUP;
>> +
>> +       if (!argc)
>
> Do you mean?
>
>     if (argc != 1)

doh! Yes I meant that.

>
>> +               usage("git submodule--helper module_name <path>\n");
>> +
>> +       memset(&config_source, 0, sizeof(config_source));
>> +       config_source.file = ".gitmodules";
>> +
>> +       if (git_config_with_options(collect_module_names, &values,
>> +                                   &config_source, 1) < 0)
>> +               die(_("unknown error occured while reading the git modules file"));
>> +
>> +       item = string_list_lookup(&values, argv[0]);
>> +       if (item)
>> +               printf("%s\n", (char*)item->util);
>> +       else
>> +               die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
>> +       return 0;
>> +}
>> +
>>  int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>>  {
>>         if (argc < 2)
>> @@ -106,6 +150,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>>         if (!strcmp(argv[1], "module_list"))
>>                 return module_list(argc - 1, argv + 1, prefix);
>>
>> +       if (!strcmp(argv[1], "module_name"))
>> +               return module_name(argc - 2, argv + 2, prefix);
>> +
>>  usage:
>>         usage("git submodule--helper module_list\n");
>>  }

^ permalink raw reply	[relevance 4%]

* Re: [PATCH 1/4] submodule: implement `module_list` as a builtin helper
  2015-08-05  0:04 19% [PATCH 1/4] submodule: implement `module_list` as a builtin helper Stefan Beller
  2015-08-05  0:04 23% ` [PATCH 2/4] submodule: implement `module_name` " Stefan Beller
@ 2015-08-05 18:31  6% ` Jens Lehmann
  2015-08-07 19:53  4% ` Junio C Hamano
  2 siblings, 0 replies; 200+ results
From: Jens Lehmann @ 2015-08-05 18:31 UTC (permalink / raw)
  To: Stefan Beller, gitster; +Cc: git, hvoigt

Am 05.08.2015 um 02:04 schrieb Stefan Beller:
> Most of the submodule operations work on a set of submodules.
> Calculating and using this set is usually done via:
>
>         module_list "$@" | {
>             while read mode sha1 stage sm_path
>             do
>                  # the actual operation
>             done
>         }
>
> Currently the function `module_list` is implemented in the
> git-submodule.sh as a shell script wrapping a perl script.
> The rewrite is in C, such that it is faster and can later be
> easily adapted when other functions are rewritten in C.
>
> git-submodule.sh similar to the builtin commands will navigate
> to the top most directory of the repository and keeping the
> subdirectories as a variable. As the helper is called from
> within the git-submodule.sh script, we are already navigated
> to the root level, but the path arguments are stil relative
> to the subdirectory we were in when calling git-submodule.sh.
> That's why there is a `--prefix` option pointing to an alternative
> path where to anchor relative path arguments.

Great you are working on this! I'll try to help, but you might
see some latency as my Git time budget is currently very limited.

I think this patch is definitely going into the right direction.
The whole test suite runs 3 seconds faster for me with this
applied: best of three is 3:16 without and 3:13 with this patch.
That's quite an improvement, especially as only parts of the test
suite deal with submodules! (And I expect Windows users to profit
even more, considered how expensive forking is there)

Acked-by: Jens Lehmann <Jens.Lehmann@web.de>

> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>
> The same as yesterday evening, just an entry added to .gitignore.
>
> So we'll have a "git submodule--helper module_list" here.
>
>   .gitignore                  |   1 +
>   Makefile                    |   1 +
>   builtin.h                   |   1 +
>   builtin/submodule--helper.c | 111 ++++++++++++++++++++++++++++++++++++++++++++
>   git-submodule.sh            |  54 +++------------------
>   git.c                       |   1 +
>   6 files changed, 121 insertions(+), 48 deletions(-)
>   create mode 100644 builtin/submodule--helper.c
>
> diff --git a/.gitignore b/.gitignore
> index a685ec1..2a69ba0 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -155,6 +155,7 @@
>   /git-status
>   /git-stripspace
>   /git-submodule
> +/git-submodule--helper
>   /git-svn
>   /git-symbolic-ref
>   /git-tag
> diff --git a/Makefile b/Makefile
> index 7efedbe..460d17a 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -899,6 +899,7 @@ BUILTIN_OBJS += builtin/shortlog.o
>   BUILTIN_OBJS += builtin/show-branch.o
>   BUILTIN_OBJS += builtin/show-ref.o
>   BUILTIN_OBJS += builtin/stripspace.o
> +BUILTIN_OBJS += builtin/submodule--helper.o
>   BUILTIN_OBJS += builtin/symbolic-ref.o
>   BUILTIN_OBJS += builtin/tag.o
>   BUILTIN_OBJS += builtin/unpack-file.o
> diff --git a/builtin.h b/builtin.h
> index 839483d..924e6c4 100644
> --- a/builtin.h
> +++ b/builtin.h
> @@ -119,6 +119,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
>   extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
>   extern int cmd_status(int argc, const char **argv, const char *prefix);
>   extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
> +extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
>   extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
>   extern int cmd_tag(int argc, const char **argv, const char *prefix);
>   extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> new file mode 100644
> index 0000000..cb18ddf
> --- /dev/null
> +++ b/builtin/submodule--helper.c
> @@ -0,0 +1,111 @@
> +#include "builtin.h"
> +#include "cache.h"
> +#include "parse-options.h"
> +#include "quote.h"
> +#include "pathspec.h"
> +#include "dir.h"
> +#include "utf8.h"
> +
> +static char *ps_matched;
> +static const struct cache_entry **ce_entries;
> +static int ce_alloc, ce_used;
> +static struct pathspec pathspec;
> +static const char *alternative_path;
> +
> +static void module_list_compute(int argc, const char **argv,
> +				const char *prefix,
> +				struct pathspec *pathspec)
> +{
> +	int i;
> +	char *max_prefix;
> +	int max_prefix_len;
> +	parse_pathspec(pathspec, 0,
> +		       PATHSPEC_PREFER_FULL |
> +		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
> +		       prefix, argv);
> +
> +	/* Find common prefix for all pathspec's */
> +	max_prefix = common_prefix(pathspec);
> +	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
> +
> +	if (pathspec->nr)
> +		ps_matched = xcalloc(1, pathspec->nr);
> +
> +
> +	if (read_cache() < 0)
> +		die("index file corrupt");
> +
> +	for (i = 0; i < active_nr; i++) {
> +		const struct cache_entry *ce = active_cache[i];
> +
> +		if (!match_pathspec(pathspec, ce->name, ce_namelen(ce),
> +				    max_prefix_len, ps_matched,
> +				    S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode)))
> +			continue;
> +
> +		if (S_ISGITLINK(ce->ce_mode)) {
> +			ALLOC_GROW(ce_entries, ce_used + 1, ce_alloc);
> +			ce_entries[ce_used++] = ce;
> +		}
> +	}
> +}
> +
> +static int module_list(int argc, const char **argv, const char *prefix)
> +{
> +	int i;
> +	struct string_list already_printed = STRING_LIST_INIT_NODUP;
> +
> +	struct option module_list_options[] = {
> +		OPT_STRING(0, "prefix", &alternative_path,
> +			   N_("path"),
> +			   N_("alternative anchor for relative paths")),
> +		OPT_END()
> +	};
> +
> +	static const char * const git_submodule_helper_usage[] = {
> +		N_("git submodule--helper module_list [--prefix=<path>] [<path>...]"),
> +		NULL
> +	};
> +
> +	argc = parse_options(argc, argv, prefix, module_list_options,
> +			     git_submodule_helper_usage, 0);
> +
> +	module_list_compute(argc, argv, alternative_path
> +					? alternative_path
> +					: prefix, &pathspec);
> +
> +	if (ps_matched && report_path_error(ps_matched, &pathspec, prefix)) {
> +		printf("#unmatched\n");
> +		return 1;
> +	}
> +
> +	for (i = 0; i < ce_used; i++) {
> +		const struct cache_entry *ce = ce_entries[i];
> +
> +		if (string_list_has_string(&already_printed, ce->name))
> +			continue;
> +
> +		if (ce_stage(ce)) {
> +			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
> +		} else {
> +			printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce));
> +		}
> +
> +		utf8_fprintf(stdout, "%s\n", ce->name);
> +
> +		string_list_insert(&already_printed, ce->name);
> +	}
> +	return 0;
> +}
> +
> +int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
> +{
> +	if (argc < 2)
> +		goto usage;
> +
> +	if (!strcmp(argv[1], "module_list"))
> +		return module_list(argc - 1, argv + 1, prefix);
> +
> +usage:
> +	usage("git submodule--helper module_list\n");
> +}
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 36797c3..af9ecef 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -145,48 +145,6 @@ relative_path ()
>   	echo "$result$target"
>   }
>
> -#
> -# Get submodule info for registered submodules
> -# $@ = path to limit submodule list
> -#
> -module_list()
> -{
> -	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
> -	(
> -		git ls-files -z --error-unmatch --stage -- "$@" ||
> -		echo "unmatched pathspec exists"
> -	) |
> -	@@PERL@@ -e '
> -	my %unmerged = ();
> -	my ($null_sha1) = ("0" x 40);
> -	my @out = ();
> -	my $unmatched = 0;
> -	$/ = "\0";
> -	while (<STDIN>) {
> -		if (/^unmatched pathspec/) {
> -			$unmatched = 1;
> -			next;
> -		}
> -		chomp;
> -		my ($mode, $sha1, $stage, $path) =
> -			/^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
> -		next unless $mode eq "160000";
> -		if ($stage ne "0") {
> -			if (!$unmerged{$path}++) {
> -				push @out, "$mode $null_sha1 U\t$path\n";
> -			}
> -			next;
> -		}
> -		push @out, "$_\n";
> -	}
> -	if ($unmatched) {
> -		print "#unmatched\n";
> -	} else {
> -		print for (@out);
> -	}
> -	'
> -}
> -
>   die_if_unmatched ()
>   {
>   	if test "$1" = "#unmatched"
> @@ -532,7 +490,7 @@ cmd_foreach()
>   	# command in the subshell (and a recursive call to this function)
>   	exec 3<&0
>
> -	module_list |
> +	git submodule--helper module_list --prefix "$wt_prefix"|
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> @@ -592,7 +550,7 @@ cmd_init()
>   		shift
>   	done
>
> -	module_list "$@" |
> +	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> @@ -674,7 +632,7 @@ cmd_deinit()
>   		die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
>   	fi
>
> -	module_list "$@" |
> +	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> @@ -790,7 +748,7 @@ cmd_update()
>   	fi
>
>   	cloned_modules=
> -	module_list "$@" | {
> +	git submodule--helper module_list --prefix "$wt_prefix" "$@" | {
>   	err=
>   	while read mode sha1 stage sm_path
>   	do
> @@ -1222,7 +1180,7 @@ cmd_status()
>   		shift
>   	done
>
> -	module_list "$@" |
> +	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> @@ -1299,7 +1257,7 @@ cmd_sync()
>   		esac
>   	done
>   	cd_to_toplevel
> -	module_list "$@" |
> +	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> diff --git a/git.c b/git.c
> index 55c327c..deecba0 100644
> --- a/git.c
> +++ b/git.c
> @@ -469,6 +469,7 @@ static struct cmd_struct commands[] = {
>   	{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
>   	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
>   	{ "stripspace", cmd_stripspace },
> +	{ "submodule--helper", cmd_submodule__helper, RUN_SETUP },
>   	{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
>   	{ "tag", cmd_tag, RUN_SETUP },
>   	{ "unpack-file", cmd_unpack_file, RUN_SETUP },
>

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 2/4] submodule: implement `module_name` as a builtin helper
  2015-08-05  0:04 23% ` [PATCH 2/4] submodule: implement `module_name` " Stefan Beller
  2015-08-05  0:05  4%   ` Stefan Beller
  2015-08-05  0:58  4%   ` Eric Sunshine
@ 2015-08-05 19:06  7%   ` Jens Lehmann
  2015-08-05 19:55  7%     ` Stefan Beller
  2 siblings, 1 reply; 200+ results
From: Jens Lehmann @ 2015-08-05 19:06 UTC (permalink / raw)
  To: Stefan Beller, gitster; +Cc: git, hvoigt

Am 05.08.2015 um 02:04 schrieb Stefan Beller:
> The goal of this series being rewriting `git submodule update`,
> we don't want to call out to the shell script for config lookups.
>
> So reimplement the lookup of the submodule name in C.

Cool. This brings down the duration of the test suite from 3:13
to 3:12 for me (best of three).

You might wanna have a look into submodule.c: after initially
calling gitmodules_config() one can lookup the submodule name
in the static "config_name_for_path" string_list. If you'd add
a public method to submodule.c which accesses that string_list
and returns the name for the given path, you won't need your
two new functions ... or am I missing something?

> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>
>   When I started to implement git submodule add in the helper, I realized
>   the very first thing to be done would be module_name translated to C,
>   so I did that separately. Maybe we need to split this up as well into two
>   separate steps for processing and I/O, such that it can be reused better
>   from a future "git submodule--helper update" function
>
>   builtin/submodule--helper.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
>   git-submodule.sh            | 32 +++++++-----------------------
>   2 files changed, 54 insertions(+), 25 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index cb18ddf..dd5635f 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -5,6 +5,8 @@
>   #include "pathspec.h"
>   #include "dir.h"
>   #include "utf8.h"
> +#include "run-command.h"
> +#include "string-list.h"
>
>   static char *ps_matched;
>   static const struct cache_entry **ce_entries;
> @@ -98,6 +100,48 @@ static int module_list(int argc, const char **argv, const char *prefix)
>   	return 0;
>   }
>
> +
> +static int collect_module_names(const char *key, const char *value, void *cb)
> +{
> +	size_t len;
> +	struct string_list *sl = cb;
> +
> +	if (starts_with(key, "submodule.")
> +	    && strip_suffix(key, ".path", &len)) {
> +		struct strbuf sb = STRBUF_INIT;
> +		strbuf_add(&sb, key + strlen("submodule."),
> +				len - strlen("submodule."));
> +		string_list_insert(sl, value)->util = strbuf_detach(&sb, NULL);
> +		strbuf_release(&sb);
> +	}
> +
> +	return 0;
> +}
> +
> +static int module_name(int argc, const char **argv, const char *prefix)
> +{
> +	struct string_list_item *item;
> +	struct git_config_source config_source;
> +	struct string_list values = STRING_LIST_INIT_DUP;
> +
> +	if (!argc)
> +		usage("git submodule--helper module_name <path>\n");
> +
> +	memset(&config_source, 0, sizeof(config_source));
> +	config_source.file = ".gitmodules";
> +
> +	if (git_config_with_options(collect_module_names, &values,
> +				    &config_source, 1) < 0)
> +		die(_("unknown error occured while reading the git modules file"));
> +
> +	item = string_list_lookup(&values, argv[0]);
> +	if (item)
> +		printf("%s\n", (char*)item->util);
> +	else
> +		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
> +	return 0;
> +}
> +
>   int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>   {
>   	if (argc < 2)
> @@ -106,6 +150,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>   	if (!strcmp(argv[1], "module_list"))
>   		return module_list(argc - 1, argv + 1, prefix);
>
> +	if (!strcmp(argv[1], "module_name"))
> +		return module_name(argc - 2, argv + 2, prefix);
> +
>   usage:
>   	usage("git submodule--helper module_list\n");
>   }
> diff --git a/git-submodule.sh b/git-submodule.sh
> index af9ecef..e6ff38d 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -178,24 +178,6 @@ get_submodule_config () {
>   	printf '%s' "${value:-$default}"
>   }
>
> -
> -#
> -# Map submodule path to submodule name
> -#
> -# $1 = path
> -#
> -module_name()
> -{
> -	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
> -	sm_path="$1"
> -	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
> -	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
> -		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
> -	test -z "$name" &&
> -	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
> -	printf '%s\n' "$name"
> -}
> -
>   #
>   # Clone a submodule
>   #
> @@ -498,7 +480,7 @@ cmd_foreach()
>   		then
>   			displaypath=$(relative_path "$sm_path")
>   			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
> -			name=$(module_name "$sm_path")
> +			name=$(git submodule--helper module_name "$sm_path")
>   			(
>   				prefix="$prefix$sm_path/"
>   				clear_local_git_env
> @@ -554,7 +536,7 @@ cmd_init()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>
>   		displaypath=$(relative_path "$sm_path")
>
> @@ -636,7 +618,7 @@ cmd_deinit()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>
>   		displaypath=$(relative_path "$sm_path")
>
> @@ -758,7 +740,7 @@ cmd_update()
>   			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
>   			continue
>   		fi
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>   		url=$(git config submodule."$name".url)
>   		branch=$(get_submodule_config "$name" branch master)
>   		if ! test -z "$update"
> @@ -1022,7 +1004,7 @@ cmd_summary() {
>   			# Respect the ignore setting for --for-status.
>   			if test -n "$for_status"
>   			then
> -				name=$(module_name "$sm_path")
> +				name=$(git submodule--helper module_name "$sm_path")
>   				ignore_config=$(get_submodule_config "$name" ignore none)
>   				test $status != A && test $ignore_config = all && continue
>   			fi
> @@ -1184,7 +1166,7 @@ cmd_status()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>   		url=$(git config submodule."$name".url)
>   		displaypath=$(relative_path "$prefix$sm_path")
>   		if test "$stage" = U
> @@ -1261,7 +1243,7 @@ cmd_sync()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path")
> +		name=$(git submodule--helper module_name "$sm_path")
>   		url=$(git config -f .gitmodules --get submodule."$name".url)
>
>   		# Possibly a url relative to parent
>

^ permalink raw reply	[relevance 7%]

* Re: [PATCH 2/4] submodule: implement `module_name` as a builtin helper
  2015-08-05 19:06  7%   ` Jens Lehmann
@ 2015-08-05 19:55  7%     ` Stefan Beller
  2015-08-05 21:08 23%       ` [PATCH] " Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-05 19:55 UTC (permalink / raw)
  To: Jens Lehmann; +Cc: Junio C Hamano, git@vger.kernel.org, Heiko Voigt

On Wed, Aug 5, 2015 at 12:06 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
> Am 05.08.2015 um 02:04 schrieb Stefan Beller:
>>
>> The goal of this series being rewriting `git submodule update`,
>> we don't want to call out to the shell script for config lookups.
>>
>> So reimplement the lookup of the submodule name in C.
>
>
> Cool. This brings down the duration of the test suite from 3:13
> to 3:12 for me (best of three).
>
> You might wanna have a look into submodule.c: after initially
> calling gitmodules_config() one can lookup the submodule name
> in the static "config_name_for_path" string_list. If you'd add
> a public method to submodule.c which accesses that string_list
> and returns the name for the given path, you won't need your
> two new functions ... or am I missing something?

Yes I just realized there is already lots of submodule related code
written in C, so I wanted to look at that as the next step and see what
can be reused and maybe redo the patches reusing code.

^ permalink raw reply	[relevance 7%]

* [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-05 19:55  7%     ` Stefan Beller
@ 2015-08-05 21:08 23%       ` Stefan Beller
  2015-08-06 19:49  6%         ` Jens Lehmann
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-05 21:08 UTC (permalink / raw)
  To: gitster; +Cc: Jens.Lehmann, hvoigt, git, Stefan Beller

This implements the helper `module_name` in C instead of shell,
yielding a nice performance boost.

Before this patch, I measured a time (best out of three):

  $ time ./t7400-submodule-basic.sh  >/dev/null
    real	0m11.066s
    user	0m3.348s
    sys	0m8.534s

With this patch applied I measured (also best out of three)

  $ time ./t7400-submodule-basic.sh  >/dev/null
    real	0m10.063s
    user	0m3.044s
    sys	0m7.487s

Signed-off-by: Stefan Beller <sbeller@google.com>
---

Is this what you had in mind, Jens?

Jonathan pointed me to https://github.com/jlehmann/git-submod-enhancements/wiki
Does it reflect reality (i.e. as time passes code changes)?

I also noticed that you have made quite some changes to submodules on different
branches which are not upstream. Soem changes look familiar (as in "I believe
this is upstream alreaday?" while others look new and exciting to me).
I could not quite get the order yet, though.

 builtin/submodule--helper.c | 23 +++++++++++++++++++++++
 git-submodule.sh            | 32 +++++++-------------------------
 submodule.c                 | 18 +++++++++++++-----
 submodule.h                 |  1 +
 4 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index cb18ddf..3713c4c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -5,6 +5,8 @@
 #include "pathspec.h"
 #include "dir.h"
 #include "utf8.h"
+#include "submodule.h"
+#include "string-list.h"
 
 static char *ps_matched;
 static const struct cache_entry **ce_entries;
@@ -98,6 +100,24 @@ static int module_list(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static int module_name(int argc, const char **argv, const char *prefix)
+{
+	const char *name;
+
+	if (argc != 1)
+		usage("git submodule--helper module_name <path>\n");
+
+	gitmodules_config();
+	name = submodule_name_for_path(argv[0]);
+
+	if (name)
+		printf("%s\n", name);
+	else
+		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
+
+	return 0;
+}
+
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 {
 	if (argc < 2)
@@ -106,6 +126,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 	if (!strcmp(argv[1], "module_list"))
 		return module_list(argc - 1, argv + 1, prefix);
 
+	if (!strcmp(argv[1], "module_name"))
+		return module_name(argc - 2, argv + 2, prefix);
+
 usage:
 	usage("git submodule--helper module_list\n");
 }
diff --git a/git-submodule.sh b/git-submodule.sh
index af9ecef..e6ff38d 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -178,24 +178,6 @@ get_submodule_config () {
 	printf '%s' "${value:-$default}"
 }
 
-
-#
-# Map submodule path to submodule name
-#
-# $1 = path
-#
-module_name()
-{
-	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
-	sm_path="$1"
-	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
-	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
-		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
-	test -z "$name" &&
-	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
-	printf '%s\n' "$name"
-}
-
 #
 # Clone a submodule
 #
@@ -498,7 +480,7 @@ cmd_foreach()
 		then
 			displaypath=$(relative_path "$sm_path")
 			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
-			name=$(module_name "$sm_path")
+			name=$(git submodule--helper module_name "$sm_path")
 			(
 				prefix="$prefix$sm_path/"
 				clear_local_git_env
@@ -554,7 +536,7 @@ cmd_init()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -636,7 +618,7 @@ cmd_deinit()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -758,7 +740,7 @@ cmd_update()
 			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 			continue
 		fi
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		branch=$(get_submodule_config "$name" branch master)
 		if ! test -z "$update"
@@ -1022,7 +1004,7 @@ cmd_summary() {
 			# Respect the ignore setting for --for-status.
 			if test -n "$for_status"
 			then
-				name=$(module_name "$sm_path")
+				name=$(git submodule--helper module_name "$sm_path")
 				ignore_config=$(get_submodule_config "$name" ignore none)
 				test $status != A && test $ignore_config = all && continue
 			fi
@@ -1184,7 +1166,7 @@ cmd_status()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		displaypath=$(relative_path "$prefix$sm_path")
 		if test "$stage" = U
@@ -1261,7 +1243,7 @@ cmd_sync()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path")
+		name=$(git submodule--helper module_name "$sm_path")
 		url=$(git config -f .gitmodules --get submodule."$name".url)
 
 		# Possibly a url relative to parent
diff --git a/submodule.c b/submodule.c
index 700bbf4..dd8dcb0 100644
--- a/submodule.c
+++ b/submodule.c
@@ -686,6 +686,16 @@ static void calculate_changed_submodule_paths(void)
 	initialized_fetch_ref_tips = 0;
 }
 
+const char* submodule_name_for_path(const char* path)
+{
+	struct string_list_item *item;
+	item = unsorted_string_list_lookup(&config_name_for_path, path);
+	if (item)
+		return item->util;
+	else
+		return NULL;
+}
+
 int fetch_populated_submodules(const struct argv_array *options,
 			       const char *prefix, int command_line_option,
 			       int quiet)
@@ -693,7 +703,7 @@ int fetch_populated_submodules(const struct argv_array *options,
 	int i, result = 0;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	struct argv_array argv = ARGV_ARRAY_INIT;
-	struct string_list_item *name_for_path;
+	const char *name_for_path;
 	const char *work_tree = get_git_work_tree();
 	if (!work_tree)
 		goto out;
@@ -723,10 +733,8 @@ int fetch_populated_submodules(const struct argv_array *options,
 		if (!S_ISGITLINK(ce->ce_mode))
 			continue;
 
-		name = ce->name;
-		name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
-		if (name_for_path)
-			name = name_for_path->util;
+		name_for_path = submodule_name_for_path(ce->name);
+		name =  name_for_path ? name_for_path : ce->name;
 
 		default_argv = "yes";
 		if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
diff --git a/submodule.h b/submodule.h
index 7beec48..e3dd854 100644
--- a/submodule.h
+++ b/submodule.h
@@ -41,5 +41,6 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam
 		struct string_list *needs_pushing);
 int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
 void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
+const char* submodule_name_for_path(const char* path);
 
 #endif
-- 
2.5.0.236.g32a3769

^ permalink raw reply related	[relevance 23%]

* [PATCH 1/4] submodule: implement `module_name` as a builtin helper
  2015-08-06 17:35  9% [RFC/PATCH 0/4] parallel fetch for submodules Stefan Beller
@ 2015-08-06 17:35 24% ` Stefan Beller
  2015-08-06 19:49  7%   ` Jens Lehmann
  2015-08-06 17:35 21% ` [RFC PATCH 4/4] submodule: add infrastructure to fetch submodules in parallel Stefan Beller
  2015-08-06 20:08  4% ` [RFC/PATCH 0/4] parallel fetch for submodules Jens Lehmann
  2 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-06 17:35 UTC (permalink / raw)
  To: git; +Cc: gitster, hvoigt, Jens.Lehmann, Stefan Beller

This implements the helper `module_name` in C instead of shell,
yielding a nice performance boost.

Before this patch, I measured a time (best out of three):

  $ time ./t7400-submodule-basic.sh  >/dev/null
    real	0m11.066s
    user	0m3.348s
    sys	0m8.534s

With this patch applied I measured (also best out of three)

  $ time ./t7400-submodule-basic.sh  >/dev/null
    real	0m10.063s
    user	0m3.044s
    sys	0m7.487s

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 builtin/submodule--helper.c | 23 +++++++++++++++++++++++
 git-submodule.sh            | 32 +++++++-------------------------
 submodule.c                 | 18 +++++++++++++-----
 submodule.h                 |  1 +
 4 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index cb18ddf..3713c4c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -5,6 +5,8 @@
 #include "pathspec.h"
 #include "dir.h"
 #include "utf8.h"
+#include "submodule.h"
+#include "string-list.h"
 
 static char *ps_matched;
 static const struct cache_entry **ce_entries;
@@ -98,6 +100,24 @@ static int module_list(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static int module_name(int argc, const char **argv, const char *prefix)
+{
+	const char *name;
+
+	if (argc != 1)
+		usage("git submodule--helper module_name <path>\n");
+
+	gitmodules_config();
+	name = submodule_name_for_path(argv[0]);
+
+	if (name)
+		printf("%s\n", name);
+	else
+		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
+
+	return 0;
+}
+
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 {
 	if (argc < 2)
@@ -106,6 +126,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 	if (!strcmp(argv[1], "module_list"))
 		return module_list(argc - 1, argv + 1, prefix);
 
+	if (!strcmp(argv[1], "module_name"))
+		return module_name(argc - 2, argv + 2, prefix);
+
 usage:
 	usage("git submodule--helper module_list\n");
 }
diff --git a/git-submodule.sh b/git-submodule.sh
index af9ecef..e6ff38d 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -178,24 +178,6 @@ get_submodule_config () {
 	printf '%s' "${value:-$default}"
 }
 
-
-#
-# Map submodule path to submodule name
-#
-# $1 = path
-#
-module_name()
-{
-	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
-	sm_path="$1"
-	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
-	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
-		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
-	test -z "$name" &&
-	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
-	printf '%s\n' "$name"
-}
-
 #
 # Clone a submodule
 #
@@ -498,7 +480,7 @@ cmd_foreach()
 		then
 			displaypath=$(relative_path "$sm_path")
 			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
-			name=$(module_name "$sm_path")
+			name=$(git submodule--helper module_name "$sm_path")
 			(
 				prefix="$prefix$sm_path/"
 				clear_local_git_env
@@ -554,7 +536,7 @@ cmd_init()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -636,7 +618,7 @@ cmd_deinit()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -758,7 +740,7 @@ cmd_update()
 			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 			continue
 		fi
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		branch=$(get_submodule_config "$name" branch master)
 		if ! test -z "$update"
@@ -1022,7 +1004,7 @@ cmd_summary() {
 			# Respect the ignore setting for --for-status.
 			if test -n "$for_status"
 			then
-				name=$(module_name "$sm_path")
+				name=$(git submodule--helper module_name "$sm_path")
 				ignore_config=$(get_submodule_config "$name" ignore none)
 				test $status != A && test $ignore_config = all && continue
 			fi
@@ -1184,7 +1166,7 @@ cmd_status()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		displaypath=$(relative_path "$prefix$sm_path")
 		if test "$stage" = U
@@ -1261,7 +1243,7 @@ cmd_sync()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path")
+		name=$(git submodule--helper module_name "$sm_path")
 		url=$(git config -f .gitmodules --get submodule."$name".url)
 
 		# Possibly a url relative to parent
diff --git a/submodule.c b/submodule.c
index 15e90d1..872967f 100644
--- a/submodule.c
+++ b/submodule.c
@@ -686,6 +686,16 @@ static void calculate_changed_submodule_paths(void)
 	initialized_fetch_ref_tips = 0;
 }
 
+const char* submodule_name_for_path(const char* path)
+{
+	struct string_list_item *item;
+	item = unsorted_string_list_lookup(&config_name_for_path, path);
+	if (item)
+		return item->util;
+	else
+		return NULL;
+}
+
 int fetch_populated_submodules(const struct argv_array *options,
 			       const char *prefix, int command_line_option,
 			       int quiet)
@@ -693,7 +703,7 @@ int fetch_populated_submodules(const struct argv_array *options,
 	int i, result = 0;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	struct argv_array argv = ARGV_ARRAY_INIT;
-	struct string_list_item *name_for_path;
+	const char *name_for_path;
 	const char *work_tree = get_git_work_tree();
 	if (!work_tree)
 		goto out;
@@ -723,10 +733,8 @@ int fetch_populated_submodules(const struct argv_array *options,
 		if (!S_ISGITLINK(ce->ce_mode))
 			continue;
 
-		name = ce->name;
-		name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
-		if (name_for_path)
-			name = name_for_path->util;
+		name_for_path = submodule_name_for_path(ce->name);
+		name =  name_for_path ? name_for_path : ce->name;
 
 		default_argv = "yes";
 		if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
diff --git a/submodule.h b/submodule.h
index 7beec48..e3dd854 100644
--- a/submodule.h
+++ b/submodule.h
@@ -41,5 +41,6 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam
 		struct string_list *needs_pushing);
 int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
 void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
+const char* submodule_name_for_path(const char* path);
 
 #endif
-- 
2.5.0.239.g9728e1d.dirty

^ permalink raw reply related	[relevance 24%]

* [RFC/PATCH 0/4] parallel fetch for submodules
@ 2015-08-06 17:35  9% Stefan Beller
  2015-08-06 17:35 24% ` [PATCH 1/4] submodule: implement `module_name` as a builtin helper Stefan Beller
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Stefan Beller @ 2015-08-06 17:35 UTC (permalink / raw)
  To: git; +Cc: gitster, hvoigt, Jens.Lehmann, Stefan Beller

When I was looking at the branches of Jens for work done on submodules
not yet upstream I found a commit "WIP threaded submodule fetching[1],
and I was side tracked wanting to present a different approach to that.

The first patch is a bit unrelated as it relates to the rewrite of git-submodule.sh
but also has code in submodule.c and the following patches modify code just around
that, so I did not remove that patch from this series. It is the same I sent 
yesterday.

The next patch 2/4 presents a framework for parallel threaded work.
It allows to setup a worker pool of <n> threads and then have a queue
of tasks which are worked on by the threads. The patch is a the one which
I'd request most comments on as I think that can be reused in a variety of
situations (parallel checkout of files, parallel fetch of different remotes,
or such).

I consider the third patch farely boring as it adds argv_array_copy, so I
would not expect much discussion there.

The last patch 4/4 presents the new workdispatcher from 2/4 in use
with just one unsolved problem of how to handle the output of the
parallel commands to stdout and stderr. It may be useful to put
handling of parallel outputs into the work dispatcher.

[1] https://github.com/jlehmann/git-submod-enhancements/commit/47597753206d40e234a47392e258065c9489e2b3

This series applies on top of origin/sb/submodule-helper (d2c6c09ac819,
submodule: implement `module_list` as a builtin helper) and can also be found
at https://github.com/stefanbeller/git/tree/parallel-submodule-fetch

Stefan Beller (4):
  submodule: implement `module_name` as a builtin helper
  Add a workdispatcher to get work done in parallel
  argv_array: add argv_array_clone to clone an existing argv array
  submodule: add infrastructure to fetch submodules in parallel

 Makefile                    |   1 +
 argv-array.c                |  13 ++++
 argv-array.h                |   1 +
 builtin/fetch.c             |   3 +-
 builtin/submodule--helper.c |  23 ++++++
 git-submodule.sh            |  32 ++------
 submodule.c                 |  92 ++++++++++++++++------
 submodule.h                 |   3 +-
 workdispatcher.c            | 184 ++++++++++++++++++++++++++++++++++++++++++++
 workdispatcher.h            |  29 +++++++
 10 files changed, 332 insertions(+), 49 deletions(-)
 create mode 100644 workdispatcher.c
 create mode 100644 workdispatcher.h

-- 
2.5.0.239.g9728e1d.dirty

^ permalink raw reply	[relevance 9%]

* [RFC PATCH 4/4] submodule: add infrastructure to fetch submodules in parallel
  2015-08-06 17:35  9% [RFC/PATCH 0/4] parallel fetch for submodules Stefan Beller
  2015-08-06 17:35 24% ` [PATCH 1/4] submodule: implement `module_name` as a builtin helper Stefan Beller
@ 2015-08-06 17:35 21% ` Stefan Beller
  2015-08-06 20:08  4% ` [RFC/PATCH 0/4] parallel fetch for submodules Jens Lehmann
  2 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-06 17:35 UTC (permalink / raw)
  To: git; +Cc: gitster, hvoigt, Jens.Lehmann, Stefan Beller

This makes use of the new workdispatcher to fetch a number
of submodules at the same time.

Still todo: sort the output of the fetch commands. I am unsure
if this should be hooked into the workdispatcher as the problem
of sorted output will appear likely again, so a general solution
would not hurt.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 builtin/fetch.c |  3 ++-
 submodule.c     | 74 ++++++++++++++++++++++++++++++++++++++++++++-------------
 submodule.h     |  2 +-
 3 files changed, 60 insertions(+), 19 deletions(-)

diff --git a/builtin/fetch.c b/builtin/fetch.c
index 8d5b2db..9053e8b 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1207,7 +1207,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		result = fetch_populated_submodules(&options,
 						    submodule_prefix,
 						    recurse_submodules,
-						    verbosity < 0);
+						    verbosity < 0,
+						    1);
 		argv_array_clear(&options);
 	}
 
diff --git a/submodule.c b/submodule.c
index 872967f..0b2842b 100644
--- a/submodule.c
+++ b/submodule.c
@@ -11,6 +11,7 @@
 #include "sha1-array.h"
 #include "argv-array.h"
 #include "blob.h"
+#include "workdispatcher.h"
 
 static struct string_list config_name_for_path;
 static struct string_list config_fetch_recurse_submodules_for_name;
@@ -696,13 +697,49 @@ const char* submodule_name_for_path(const char* path)
 		return NULL;
 }
 
+struct submodule_parallel_fetch {
+	struct child_process cp;
+	struct argv_array argv;
+	struct strbuf sb;
+	int quiet;
+};
+
+void submodule_parallel_fetch_init(struct submodule_parallel_fetch *spf)
+{
+	child_process_init(&spf->cp);
+	argv_array_init(&spf->argv);
+	strbuf_init(&spf->sb, 0);
+	spf->quiet = 0;
+}
+
+void *run_command_and_cleanup(void *arg)
+{
+	struct submodule_parallel_fetch *spf = arg;
+	void *ret = NULL;
+
+	if (!spf->quiet)
+		puts(spf->sb.buf);
+
+	spf->cp.argv = spf->argv.argv;
+
+	if (run_command(&spf->cp))
+		ret = (void *)1;
+
+	strbuf_release(&spf->cp);
+	argv_array_clear(spf->argv);
+	free(spf);
+	return ret;
+}
+
 int fetch_populated_submodules(const struct argv_array *options,
 			       const char *prefix, int command_line_option,
-			       int quiet)
+			       int quiet, int max_parallel_jobs)
 {
 	int i, result = 0;
-	struct child_process cp = CHILD_PROCESS_INIT;
+	struct workdispatcher *wd;
+	struct return_values *rv;
 	struct argv_array argv = ARGV_ARRAY_INIT;
+	struct submodule_parallel_fetch *spf;
 	const char *name_for_path;
 	const char *work_tree = get_git_work_tree();
 	if (!work_tree)
@@ -717,12 +754,9 @@ int fetch_populated_submodules(const struct argv_array *options,
 	argv_array_push(&argv, "--recurse-submodules-default");
 	/* default value, "--submodule-prefix" and its value are added later */
 
-	cp.env = local_repo_env;
-	cp.git_cmd = 1;
-	cp.no_stdin = 1;
-
 	calculate_changed_submodule_paths();
 
+	wd = create_workdispatcher(&run_command_and_cleanup, max_parallel_jobs);
 	for (i = 0; i < active_nr; i++) {
 		struct strbuf submodule_path = STRBUF_INIT;
 		struct strbuf submodule_git_dir = STRBUF_INIT;
@@ -771,24 +805,30 @@ int fetch_populated_submodules(const struct argv_array *options,
 		if (!git_dir)
 			git_dir = submodule_git_dir.buf;
 		if (is_directory(git_dir)) {
+			spf = xmalloc(sizeof(*spf));
+			submodule_parallel_fetch_init(spf);
+			spf->cp.env = local_repo_env;
+			spf->cp.git_cmd = 1;
+			spf->cp.no_stdin = 1;
+			spf->cp.dir = strbuf_detach(&submodule_path, NULL);
+			spf->quiet = quiet;
 			if (!quiet)
-				printf("Fetching submodule %s%s\n", prefix, ce->name);
-			cp.dir = submodule_path.buf;
-			argv_array_push(&argv, default_argv);
-			argv_array_push(&argv, "--submodule-prefix");
-			argv_array_push(&argv, submodule_prefix.buf);
-			cp.argv = argv.argv;
-			if (run_command(&cp))
-				result = 1;
-			argv_array_pop(&argv);
-			argv_array_pop(&argv);
-			argv_array_pop(&argv);
+				strbuf_addf(&spf->sb, "Fetching submodule %s%s", prefix, ce->name);
+			argv_array_copy(&argv, &spf->argv);
+			argv_array_push(&spf->argv, default_argv);
+			argv_array_push(&spf->argv, "--submodule-prefix");
+			argv_array_push(&spf->argv, submodule_prefix.buf);
+			add_task(wd, spf);
 		}
 		strbuf_release(&submodule_path);
 		strbuf_release(&submodule_git_dir);
 		strbuf_release(&submodule_prefix);
 	}
 	argv_array_clear(&argv);
+	rv = wait_workdispatcher(wd);
+	for (i = 0; i < rv->count; i++)
+		if (rv->ret[i])
+			result = 1;
 out:
 	string_list_clear(&changed_submodule_paths, 1);
 	return result;
diff --git a/submodule.h b/submodule.h
index e3dd854..51195ea 100644
--- a/submodule.h
+++ b/submodule.h
@@ -31,7 +31,7 @@ void set_config_fetch_recurse_submodules(int value);
 void check_for_new_submodule_commits(unsigned char new_sha1[20]);
 int fetch_populated_submodules(const struct argv_array *options,
 			       const char *prefix, int command_line_option,
-			       int quiet);
+			       int quiet, int max_parallel_jobs);
 unsigned is_submodule_modified(const char *path, int ignore_untracked);
 int submodule_uses_gitfile(const char *path);
 int ok_to_remove_submodule(const char *path);
-- 
2.5.0.239.g9728e1d.dirty

^ permalink raw reply related	[relevance 21%]

* [PATCH 1/2] builtin/mv: remove get_pathspec()
  @ 2015-08-06 18:27  7%   ` Stefan Beller
  2015-08-06 18:46  2%     ` Eric Sunshine
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-06 18:27 UTC (permalink / raw)
  To: git, gitster; +Cc: Stefan Beller, pclouds, sunshine

`get_pathspec` is deprecated and builtin/mv.c is its last caller, so
reimplement `get_pathspec` literally in builtin/mv.c

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 builtin/mv.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/builtin/mv.c b/builtin/mv.c
index d1d4316..99e9b3c 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -10,6 +10,7 @@
 #include "string-list.h"
 #include "parse-options.h"
 #include "submodule.h"
+#include "pathspec.h"
 
 static const char * const builtin_mv_usage[] = {
 	N_("git mv [<options>] <source>... <destination>"),
@@ -20,13 +21,16 @@ static const char * const builtin_mv_usage[] = {
 #define KEEP_TRAILING_SLASH 2
 
 static const char **internal_copy_pathspec(const char *prefix,
-					   const char **pathspec,
+					   const char **argv,
 					   int count, unsigned flags)
 {
 	int i;
+	struct pathspec ps;
 	const char **result = xmalloc((count + 1) * sizeof(const char *));
-	memcpy(result, pathspec, count * sizeof(const char *));
+	memcpy(result, argv, count * sizeof(const char *));
 	result[count] = NULL;
+
+	/* NEEDSWORK: Move these preprocessing steps into parse_pathspec */
 	for (i = 0; i < count; i++) {
 		int length = strlen(result[i]);
 		int to_copy = length;
@@ -42,7 +46,13 @@ static const char **internal_copy_pathspec(const char *prefix,
 				result[i] = it;
 		}
 	}
-	return get_pathspec(prefix, result);
+
+	parse_pathspec(&ps,
+		       PATHSPEC_ALL_MAGIC &
+		       ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
+		       PATHSPEC_PREFER_CWD,
+		       prefix, result);
+	return ps._raw;
 }
 
 static const char *add_slash(const char *path)
-- 
2.5.0.239.g9728e1d.dirty

^ permalink raw reply related	[relevance 7%]

* Re: [PATCH 1/2] builtin/mv: remove get_pathspec()
  2015-08-06 18:27  7%   ` [PATCH 1/2] builtin/mv: remove get_pathspec() Stefan Beller
@ 2015-08-06 18:46  2%     ` Eric Sunshine
  2015-08-06 18:58  2%       ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Eric Sunshine @ 2015-08-06 18:46 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Git List, Junio C Hamano, Nguyễn Thái Ngọc Duy

On Thu, Aug 6, 2015 at 2:27 PM, Stefan Beller <sbeller@google.com> wrote:
>  builtin/mv: remove get_pathspec()

Misleading. Perhaps rephrase as:

    mv: drop dependency upon deprecated get_pathspec

> `get_pathspec` is deprecated and builtin/mv.c is its last caller, so
> reimplement `get_pathspec` literally in builtin/mv.c

Curious. Since this is just moving code around, rather than doing the
actual work to complete the final step as stated by the NEEDSWORK
comment, isn't it just moving the "problem" from one location to
another? Is it worth the code churn?

> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
> diff --git a/builtin/mv.c b/builtin/mv.c
> index d1d4316..99e9b3c 100644
> --- a/builtin/mv.c
> +++ b/builtin/mv.c
> @@ -10,6 +10,7 @@
>  #include "string-list.h"
>  #include "parse-options.h"
>  #include "submodule.h"
> +#include "pathspec.h"
>
>  static const char * const builtin_mv_usage[] = {
>         N_("git mv [<options>] <source>... <destination>"),
> @@ -20,13 +21,16 @@ static const char * const builtin_mv_usage[] = {
>  #define KEEP_TRAILING_SLASH 2
>
>  static const char **internal_copy_pathspec(const char *prefix,
> -                                          const char **pathspec,
> +                                          const char **argv,

What is this change about? It doesn't seem to be related to anything
else in the patch or to its stated purpose, and makes the argument's
purpose less clear, so it's not obvious why it is a good change.

>                                            int count, unsigned flags)
>  {
>         int i;
> +       struct pathspec ps;
>         const char **result = xmalloc((count + 1) * sizeof(const char *));
> -       memcpy(result, pathspec, count * sizeof(const char *));
> +       memcpy(result, argv, count * sizeof(const char *));
>         result[count] = NULL;
> +
> +       /* NEEDSWORK: Move these preprocessing steps into parse_pathspec */
>         for (i = 0; i < count; i++) {
>                 int length = strlen(result[i]);
>                 int to_copy = length;
> @@ -42,7 +46,13 @@ static const char **internal_copy_pathspec(const char *prefix,
>                                 result[i] = it;
>                 }
>         }
> -       return get_pathspec(prefix, result);
> +
> +       parse_pathspec(&ps,
> +                      PATHSPEC_ALL_MAGIC &
> +                      ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
> +                      PATHSPEC_PREFER_CWD,
> +                      prefix, result);
> +       return ps._raw;
>  }
>
>  static const char *add_slash(const char *path)
> --
> 2.5.0.239.g9728e1d.dirty

^ permalink raw reply	[relevance 2%]

* Re: [PATCH 1/2] builtin/mv: remove get_pathspec()
  2015-08-06 18:46  2%     ` Eric Sunshine
@ 2015-08-06 18:58  2%       ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-06 18:58 UTC (permalink / raw)
  To: Eric Sunshine
  Cc: Git List, Junio C Hamano, Nguyễn Thái Ngọc Duy

On Thu, Aug 6, 2015 at 11:46 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:
> On Thu, Aug 6, 2015 at 2:27 PM, Stefan Beller <sbeller@google.com> wrote:
>>  builtin/mv: remove get_pathspec()
>
> Misleading. Perhaps rephrase as:
>
>     mv: drop dependency upon deprecated get_pathspec
>
>> `get_pathspec` is deprecated and builtin/mv.c is its last caller, so
>> reimplement `get_pathspec` literally in builtin/mv.c
>
> Curious. Since this is just moving code around, rather than doing the
> actual work to complete the final step as stated by the NEEDSWORK
> comment, isn't it just moving the "problem" from one location to
> another? Is it worth the code churn?

Yeah it is moving around the problem a bit. And the code churn is
unfortunate. Though when I was reading the documentation on
pathspecs, literally the first sentence was "Do not use get_pathspec,
it is out dated". And that was a sad taste for reading documentation.

It's ok to have such warnings in the docs, but as the first sentence as if
there was nothing more important than avoiding the out dated stuff? I
mean I want to understand the actual code and how I can use it, right?

And there are different approaches to solving the problem.
I could have just reworded or even just rearranged the documentation.

The approach I take here includes a bit of code churn, but it moves the
problematic pieces all in one spot.

>
>> Signed-off-by: Stefan Beller <sbeller@google.com>
>> ---
>> diff --git a/builtin/mv.c b/builtin/mv.c
>> index d1d4316..99e9b3c 100644
>> --- a/builtin/mv.c
>> +++ b/builtin/mv.c
>> @@ -10,6 +10,7 @@
>>  #include "string-list.h"
>>  #include "parse-options.h"
>>  #include "submodule.h"
>> +#include "pathspec.h"
>>
>>  static const char * const builtin_mv_usage[] = {
>>         N_("git mv [<options>] <source>... <destination>"),
>> @@ -20,13 +21,16 @@ static const char * const builtin_mv_usage[] = {
>>  #define KEEP_TRAILING_SLASH 2
>>
>>  static const char **internal_copy_pathspec(const char *prefix,
>> -                                          const char **pathspec,
>> +                                          const char **argv,
>
> What is this change about? It doesn't seem to be related to anything
> else in the patch or to its stated purpose, and makes the argument's
> purpose less clear, so it's not obvious why it is a good change.
>
>>                                            int count, unsigned flags)
>>  {
>>         int i;
>> +       struct pathspec ps;
>>         const char **result = xmalloc((count + 1) * sizeof(const char *));
>> -       memcpy(result, pathspec, count * sizeof(const char *));
>> +       memcpy(result, argv, count * sizeof(const char *));
>>         result[count] = NULL;
>> +
>> +       /* NEEDSWORK: Move these preprocessing steps into parse_pathspec */
>>         for (i = 0; i < count; i++) {
>>                 int length = strlen(result[i]);
>>                 int to_copy = length;
>> @@ -42,7 +46,13 @@ static const char **internal_copy_pathspec(const char *prefix,
>>                                 result[i] = it;
>>                 }
>>         }
>> -       return get_pathspec(prefix, result);
>> +
>> +       parse_pathspec(&ps,
>> +                      PATHSPEC_ALL_MAGIC &
>> +                      ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
>> +                      PATHSPEC_PREFER_CWD,
>> +                      prefix, result);
>> +       return ps._raw;
>>  }
>>
>>  static const char *add_slash(const char *path)
>> --
>> 2.5.0.239.g9728e1d.dirty

^ permalink raw reply	[relevance 2%]

* Re: [PATCH 1/4] submodule: implement `module_name` as a builtin helper
  2015-08-06 17:35 24% ` [PATCH 1/4] submodule: implement `module_name` as a builtin helper Stefan Beller
@ 2015-08-06 19:49  7%   ` Jens Lehmann
  0 siblings, 0 replies; 200+ results
From: Jens Lehmann @ 2015-08-06 19:49 UTC (permalink / raw)
  To: Stefan Beller, git; +Cc: gitster, hvoigt

Am 06.08.2015 um 19:35 schrieb Stefan Beller:
> This implements the helper `module_name` in C instead of shell,
> yielding a nice performance boost.
>
> Before this patch, I measured a time (best out of three):
>
>    $ time ./t7400-submodule-basic.sh  >/dev/null
>      real	0m11.066s
>      user	0m3.348s
>      sys	0m8.534s
>
> With this patch applied I measured (also best out of three)
>
>    $ time ./t7400-submodule-basic.sh  >/dev/null
>      real	0m10.063s
>      user	0m3.044s
>      sys	0m7.487s
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---

Please see my comments in the other thread concerning this patch.

And wouldn't it make more sense to keep this patch together with
the "submodule: implement `module_list` as a builtin helper" in
its own "submodule-helper" series and have the following three
patches in a separate "parallel fetch for submodules" series?

>   builtin/submodule--helper.c | 23 +++++++++++++++++++++++
>   git-submodule.sh            | 32 +++++++-------------------------
>   submodule.c                 | 18 +++++++++++++-----
>   submodule.h                 |  1 +
>   4 files changed, 44 insertions(+), 30 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index cb18ddf..3713c4c 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -5,6 +5,8 @@
>   #include "pathspec.h"
>   #include "dir.h"
>   #include "utf8.h"
> +#include "submodule.h"
> +#include "string-list.h"
>
>   static char *ps_matched;
>   static const struct cache_entry **ce_entries;
> @@ -98,6 +100,24 @@ static int module_list(int argc, const char **argv, const char *prefix)
>   	return 0;
>   }
>
> +static int module_name(int argc, const char **argv, const char *prefix)
> +{
> +	const char *name;
> +
> +	if (argc != 1)
> +		usage("git submodule--helper module_name <path>\n");
> +
> +	gitmodules_config();
> +	name = submodule_name_for_path(argv[0]);
> +
> +	if (name)
> +		printf("%s\n", name);
> +	else
> +		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
> +
> +	return 0;
> +}
> +
>   int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>   {
>   	if (argc < 2)
> @@ -106,6 +126,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>   	if (!strcmp(argv[1], "module_list"))
>   		return module_list(argc - 1, argv + 1, prefix);
>
> +	if (!strcmp(argv[1], "module_name"))
> +		return module_name(argc - 2, argv + 2, prefix);
> +
>   usage:
>   	usage("git submodule--helper module_list\n");
>   }
> diff --git a/git-submodule.sh b/git-submodule.sh
> index af9ecef..e6ff38d 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -178,24 +178,6 @@ get_submodule_config () {
>   	printf '%s' "${value:-$default}"
>   }
>
> -
> -#
> -# Map submodule path to submodule name
> -#
> -# $1 = path
> -#
> -module_name()
> -{
> -	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
> -	sm_path="$1"
> -	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
> -	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
> -		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
> -	test -z "$name" &&
> -	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
> -	printf '%s\n' "$name"
> -}
> -
>   #
>   # Clone a submodule
>   #
> @@ -498,7 +480,7 @@ cmd_foreach()
>   		then
>   			displaypath=$(relative_path "$sm_path")
>   			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
> -			name=$(module_name "$sm_path")
> +			name=$(git submodule--helper module_name "$sm_path")
>   			(
>   				prefix="$prefix$sm_path/"
>   				clear_local_git_env
> @@ -554,7 +536,7 @@ cmd_init()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>
>   		displaypath=$(relative_path "$sm_path")
>
> @@ -636,7 +618,7 @@ cmd_deinit()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>
>   		displaypath=$(relative_path "$sm_path")
>
> @@ -758,7 +740,7 @@ cmd_update()
>   			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
>   			continue
>   		fi
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>   		url=$(git config submodule."$name".url)
>   		branch=$(get_submodule_config "$name" branch master)
>   		if ! test -z "$update"
> @@ -1022,7 +1004,7 @@ cmd_summary() {
>   			# Respect the ignore setting for --for-status.
>   			if test -n "$for_status"
>   			then
> -				name=$(module_name "$sm_path")
> +				name=$(git submodule--helper module_name "$sm_path")
>   				ignore_config=$(get_submodule_config "$name" ignore none)
>   				test $status != A && test $ignore_config = all && continue
>   			fi
> @@ -1184,7 +1166,7 @@ cmd_status()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>   		url=$(git config submodule."$name".url)
>   		displaypath=$(relative_path "$prefix$sm_path")
>   		if test "$stage" = U
> @@ -1261,7 +1243,7 @@ cmd_sync()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path")
> +		name=$(git submodule--helper module_name "$sm_path")
>   		url=$(git config -f .gitmodules --get submodule."$name".url)
>
>   		# Possibly a url relative to parent
> diff --git a/submodule.c b/submodule.c
> index 15e90d1..872967f 100644
> --- a/submodule.c
> +++ b/submodule.c
> @@ -686,6 +686,16 @@ static void calculate_changed_submodule_paths(void)
>   	initialized_fetch_ref_tips = 0;
>   }
>
> +const char* submodule_name_for_path(const char* path)
> +{
> +	struct string_list_item *item;
> +	item = unsorted_string_list_lookup(&config_name_for_path, path);
> +	if (item)
> +		return item->util;
> +	else
> +		return NULL;
> +}
> +
>   int fetch_populated_submodules(const struct argv_array *options,
>   			       const char *prefix, int command_line_option,
>   			       int quiet)
> @@ -693,7 +703,7 @@ int fetch_populated_submodules(const struct argv_array *options,
>   	int i, result = 0;
>   	struct child_process cp = CHILD_PROCESS_INIT;
>   	struct argv_array argv = ARGV_ARRAY_INIT;
> -	struct string_list_item *name_for_path;
> +	const char *name_for_path;
>   	const char *work_tree = get_git_work_tree();
>   	if (!work_tree)
>   		goto out;
> @@ -723,10 +733,8 @@ int fetch_populated_submodules(const struct argv_array *options,
>   		if (!S_ISGITLINK(ce->ce_mode))
>   			continue;
>
> -		name = ce->name;
> -		name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
> -		if (name_for_path)
> -			name = name_for_path->util;
> +		name_for_path = submodule_name_for_path(ce->name);
> +		name =  name_for_path ? name_for_path : ce->name;
>
>   		default_argv = "yes";
>   		if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
> diff --git a/submodule.h b/submodule.h
> index 7beec48..e3dd854 100644
> --- a/submodule.h
> +++ b/submodule.h
> @@ -41,5 +41,6 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam
>   		struct string_list *needs_pushing);
>   int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
>   void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
> +const char* submodule_name_for_path(const char* path);
>
>   #endif
>

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-05 21:08 23%       ` [PATCH] " Stefan Beller
@ 2015-08-06 19:49  6%         ` Jens Lehmann
  2015-08-06 21:38 24%           ` Stefan Beller
    0 siblings, 2 replies; 200+ results
From: Jens Lehmann @ 2015-08-06 19:49 UTC (permalink / raw)
  To: Stefan Beller, gitster; +Cc: hvoigt, git

Am 05.08.2015 um 23:08 schrieb Stefan Beller:
> This implements the helper `module_name` in C instead of shell,
> yielding a nice performance boost.
>
> Before this patch, I measured a time (best out of three):
>
>    $ time ./t7400-submodule-basic.sh  >/dev/null
>      real	0m11.066s
>      user	0m3.348s
>      sys	0m8.534s
>
> With this patch applied I measured (also best out of three)
>
>    $ time ./t7400-submodule-basic.sh  >/dev/null
>      real	0m10.063s
>      user	0m3.044s
>      sys	0m7.487s
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>
> Is this what you had in mind, Jens?

Yup, thanks!

Just some small nits, please see below (and also in the fixup! commit
I pushed on the "submodule--helper" branch in my Github repo).

> Jonathan pointed me to https://github.com/jlehmann/git-submod-enhancements/wiki
> Does it reflect reality (i.e. as time passes code changes)?
 >
> I also noticed that you have made quite some changes to submodules on different
> branches which are not upstream. Soem changes look familiar (as in "I believe
> this is upstream alreaday?" while others look new and exciting to me).
> I could not quite get the order yet, though.

I think the Wiki should be pretty much up to date, but I'll try to check
that and the state of the branches on the weekend to see if it needs an
update. If you see some branches you believe are already upstream, it'd
be great if you could mention them so I can double check.

>   builtin/submodule--helper.c | 23 +++++++++++++++++++++++
>   git-submodule.sh            | 32 +++++++-------------------------
>   submodule.c                 | 18 +++++++++++++-----
>   submodule.h                 |  1 +
>   4 files changed, 44 insertions(+), 30 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index cb18ddf..3713c4c 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -5,6 +5,8 @@
>   #include "pathspec.h"
>   #include "dir.h"
>   #include "utf8.h"
> +#include "submodule.h"
> +#include "string-list.h"
>
>   static char *ps_matched;
>   static const struct cache_entry **ce_entries;
> @@ -98,6 +100,24 @@ static int module_list(int argc, const char **argv, const char *prefix)
>   	return 0;
>   }
>
> +static int module_name(int argc, const char **argv, const char *prefix)
> +{
> +	const char *name;
> +
> +	if (argc != 1)
> +		usage("git submodule--helper module_name <path>\n");
> +
> +	gitmodules_config();
> +	name = submodule_name_for_path(argv[0]);
> +
> +	if (name)
> +		printf("%s\n", name);
> +	else
> +		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);

Hmm, I prefer the pattern to bail out inside if() and continue with the
expected case without else:

+	if (!name)
+		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
+
+	printf("%s\n", name);

But maybe that's just me.

> +	return 0;
> +}
> +
>   int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>   {
>   	if (argc < 2)
> @@ -106,6 +126,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>   	if (!strcmp(argv[1], "module_list"))
>   		return module_list(argc - 1, argv + 1, prefix);
>
> +	if (!strcmp(argv[1], "module_name"))
> +		return module_name(argc - 2, argv + 2, prefix);
> +
>   usage:
>   	usage("git submodule--helper module_list\n");
>   }
> diff --git a/git-submodule.sh b/git-submodule.sh
> index af9ecef..e6ff38d 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -178,24 +178,6 @@ get_submodule_config () {
>   	printf '%s' "${value:-$default}"
>   }
>
> -
> -#
> -# Map submodule path to submodule name
> -#
> -# $1 = path
> -#
> -module_name()
> -{
> -	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
> -	sm_path="$1"
> -	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
> -	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
> -		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
> -	test -z "$name" &&
> -	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
> -	printf '%s\n' "$name"
> -}
> -
>   #
>   # Clone a submodule
>   #
> @@ -498,7 +480,7 @@ cmd_foreach()
>   		then
>   			displaypath=$(relative_path "$sm_path")
>   			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
> -			name=$(module_name "$sm_path")
> +			name=$(git submodule--helper module_name "$sm_path")
>   			(
>   				prefix="$prefix$sm_path/"
>   				clear_local_git_env
> @@ -554,7 +536,7 @@ cmd_init()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>
>   		displaypath=$(relative_path "$sm_path")
>
> @@ -636,7 +618,7 @@ cmd_deinit()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>
>   		displaypath=$(relative_path "$sm_path")
>
> @@ -758,7 +740,7 @@ cmd_update()
>   			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
>   			continue
>   		fi
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>   		url=$(git config submodule."$name".url)
>   		branch=$(get_submodule_config "$name" branch master)
>   		if ! test -z "$update"
> @@ -1022,7 +1004,7 @@ cmd_summary() {
>   			# Respect the ignore setting for --for-status.
>   			if test -n "$for_status"
>   			then
> -				name=$(module_name "$sm_path")
> +				name=$(git submodule--helper module_name "$sm_path")
>   				ignore_config=$(get_submodule_config "$name" ignore none)
>   				test $status != A && test $ignore_config = all && continue
>   			fi
> @@ -1184,7 +1166,7 @@ cmd_status()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>   		url=$(git config submodule."$name".url)
>   		displaypath=$(relative_path "$prefix$sm_path")
>   		if test "$stage" = U
> @@ -1261,7 +1243,7 @@ cmd_sync()
>   	while read mode sha1 stage sm_path
>   	do
>   		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path")
> +		name=$(git submodule--helper module_name "$sm_path")
>   		url=$(git config -f .gitmodules --get submodule."$name".url)
>
>   		# Possibly a url relative to parent
> diff --git a/submodule.c b/submodule.c
> index 700bbf4..dd8dcb0 100644
> --- a/submodule.c
> +++ b/submodule.c
> @@ -686,6 +686,16 @@ static void calculate_changed_submodule_paths(void)
>   	initialized_fetch_ref_tips = 0;
>   }
>
> +const char* submodule_name_for_path(const char* path)

Asterisk belongs to the name, not the type:

+const char *submodule_name_for_path(const char *path)

> +{
> +	struct string_list_item *item;
> +	item = unsorted_string_list_lookup(&config_name_for_path, path);
> +	if (item)
> +		return item->util;
> +	else
> +		return NULL;

Maybe we could use the "if() bailout;" pattern here too:

+	if (!item)
+		return NULL;
+
+	return item->util;

("else" after "return" looks strange ;-)

> +}
> +
>   int fetch_populated_submodules(const struct argv_array *options,
>   			       const char *prefix, int command_line_option,
>   			       int quiet)
> @@ -693,7 +703,7 @@ int fetch_populated_submodules(const struct argv_array *options,
>   	int i, result = 0;
>   	struct child_process cp = CHILD_PROCESS_INIT;
>   	struct argv_array argv = ARGV_ARRAY_INIT;
> -	struct string_list_item *name_for_path;
> +	const char *name_for_path;
>   	const char *work_tree = get_git_work_tree();
>   	if (!work_tree)
>   		goto out;
> @@ -723,10 +733,8 @@ int fetch_populated_submodules(const struct argv_array *options,
>   		if (!S_ISGITLINK(ce->ce_mode))
>   			continue;
>
> -		name = ce->name;
> -		name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
> -		if (name_for_path)
> -			name = name_for_path->util;
> +		name_for_path = submodule_name_for_path(ce->name);
> +		name =  name_for_path ? name_for_path : ce->name;

I think we can get rid of name_for_path auto variable altogether here.
(And while at it why not add the previously missing comment why we do
fall back to the path here?):

+		name = submodule_name_for_path(ce->name);
+		if (!name)
+			/* Not in .gitmodules, try the default name == path */
+			name = ce->name;

>   		default_argv = "yes";
>   		if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
> diff --git a/submodule.h b/submodule.h
> index 7beec48..e3dd854 100644
> --- a/submodule.h
> +++ b/submodule.h
> @@ -41,5 +41,6 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam
>   		struct string_list *needs_pushing);
>   int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
>   void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
> +const char* submodule_name_for_path(const char* path);

Asterisk belongs to the names, not the type here too.

+const char *submodule_name_for_path(const char *path);

>
>   #endif
>

^ permalink raw reply	[relevance 6%]

* Re: [RFC/PATCH 0/4] parallel fetch for submodules
  2015-08-06 17:35  9% [RFC/PATCH 0/4] parallel fetch for submodules Stefan Beller
  2015-08-06 17:35 24% ` [PATCH 1/4] submodule: implement `module_name` as a builtin helper Stefan Beller
  2015-08-06 17:35 21% ` [RFC PATCH 4/4] submodule: add infrastructure to fetch submodules in parallel Stefan Beller
@ 2015-08-06 20:08  4% ` Jens Lehmann
  2015-08-06 20:44  6%   ` Stefan Beller
  2 siblings, 1 reply; 200+ results
From: Jens Lehmann @ 2015-08-06 20:08 UTC (permalink / raw)
  To: Stefan Beller, git; +Cc: gitster, hvoigt

Am 06.08.2015 um 19:35 schrieb Stefan Beller:
> When I was looking at the branches of Jens for work done on submodules
> not yet upstream I found a commit "WIP threaded submodule fetching[1],
> and I was side tracked wanting to present a different approach to that.

Cool. I didn't follow that route further than building a proof of
concept because I ran into a nasty DNS-timeout on my router at home
and at work we host all repos on a not-so-beefy server making parallel
fetch rather pointless. But I suspect this approach will bring down
fetch times for some users.

Maybe we could also re-use parallel fetch for multiple upstreams in
the superproject when doing a "git fetch --all" without too much
extra work?

^ permalink raw reply	[relevance 4%]

* Re: [RFC/PATCH 0/4] parallel fetch for submodules
  2015-08-06 20:08  4% ` [RFC/PATCH 0/4] parallel fetch for submodules Jens Lehmann
@ 2015-08-06 20:44  6%   ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-06 20:44 UTC (permalink / raw)
  To: Jens Lehmann; +Cc: git@vger.kernel.org, Junio C Hamano, Heiko Voigt

On Thu, Aug 6, 2015 at 1:08 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
> Am 06.08.2015 um 19:35 schrieb Stefan Beller:
>>
>> When I was looking at the branches of Jens for work done on submodules
>> not yet upstream I found a commit "WIP threaded submodule fetching[1],
>> and I was side tracked wanting to present a different approach to that.
>
>
> Cool. I didn't follow that route further than building a proof of
> concept because I ran into a nasty DNS-timeout on my router at home
> and at work we host all repos on a not-so-beefy server making parallel
> fetch rather pointless. But I suspect this approach will bring down
> fetch times for some users.

The difference between your proof of concept and mine is to have the number
of threads easier configurable. (Think of "git fetch --recurse-submodules=yes
 -j4", similar to "make -j4" splitting work up to 4 different programs
at the same
time. And that thing would be possible to add in this series)

If you fetch lots of submodules, both the client and server load should come
in an ping-pong on-off pattern as the client waits for the server to
prepare stuff
and get it sent to it and then the client needs time to resolve deltas
and write to
disk. Depending on the duty cycle of each, a different number of
parallel threads
make sense (I would expected that they shift their phases against each other
by pure randomness, i.e. one thread is currently resolving deltas
while the other
thread is telling the server to get some work done, so both the client
and server
get utilized at the same time).

>
> Maybe we could also re-use parallel fetch for multiple upstreams in
> the superproject when doing a "git fetch --all" without too much
> extra work?

That's why I tried advertising RFC patch 2/4 as I believe it could be
easily reused for such things like "git fetch --all", but maybe other
people see problems with it (over/under engineered, wrong things
added, but other critical things missing) so I'd like to hear opinions
on that. :)

^ permalink raw reply	[relevance 6%]

* [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-06 19:49  6%         ` Jens Lehmann
@ 2015-08-06 21:38 24%           ` Stefan Beller
  2015-08-07 20:03  7%             ` Junio C Hamano
    1 sibling, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-06 21:38 UTC (permalink / raw)
  To: gitster; +Cc: Stefan Beller, Jens.Lehmann, git, hvoigt

This implements the helper `module_name` in C instead of shell,
yielding a nice performance boost.

Before this patch, I measured a time (best out of three):

  $ time ./t7400-submodule-basic.sh  >/dev/null
    real	0m11.066s
    user	0m3.348s
    sys	0m8.534s

With this patch applied I measured (also best out of three)

  $ time ./t7400-submodule-basic.sh  >/dev/null
    real	0m10.063s
    user	0m3.044s
    sys	0m7.487s

Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Stefan Beller <sbeller@google.com>
---

This incorporates the changes from Jens fixup! commit
(which addresses all issues he pointed out).

I agree this looks much cleaner. :)

This patch advances origin/sb/submodule-helper (d2c6c09ac8,
submodule: implement `module_list` as a builtin helper)

 builtin/submodule--helper.c | 22 ++++++++++++++++++++++
 git-submodule.sh            | 32 +++++++-------------------------
 submodule.c                 | 19 ++++++++++++++-----
 submodule.h                 |  1 +
 4 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index cb18ddf..bc37b74 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -5,6 +5,8 @@
 #include "pathspec.h"
 #include "dir.h"
 #include "utf8.h"
+#include "submodule.h"
+#include "string-list.h"
 
 static char *ps_matched;
 static const struct cache_entry **ce_entries;
@@ -98,6 +100,23 @@ static int module_list(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static int module_name(int argc, const char **argv, const char *prefix)
+{
+	const char *name;
+
+	if (argc != 1)
+		usage("git submodule--helper module_name <path>\n");
+
+	gitmodules_config();
+	name = submodule_name_for_path(argv[0]);
+
+	if (!name)
+		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
+
+	printf("%s\n", name);
+	return 0;
+}
+
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 {
 	if (argc < 2)
@@ -106,6 +125,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 	if (!strcmp(argv[1], "module_list"))
 		return module_list(argc - 1, argv + 1, prefix);
 
+	if (!strcmp(argv[1], "module_name"))
+		return module_name(argc - 2, argv + 2, prefix);
+
 usage:
 	usage("git submodule--helper module_list\n");
 }
diff --git a/git-submodule.sh b/git-submodule.sh
index af9ecef..e6ff38d 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -178,24 +178,6 @@ get_submodule_config () {
 	printf '%s' "${value:-$default}"
 }
 
-
-#
-# Map submodule path to submodule name
-#
-# $1 = path
-#
-module_name()
-{
-	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
-	sm_path="$1"
-	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
-	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
-		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
-	test -z "$name" &&
-	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
-	printf '%s\n' "$name"
-}
-
 #
 # Clone a submodule
 #
@@ -498,7 +480,7 @@ cmd_foreach()
 		then
 			displaypath=$(relative_path "$sm_path")
 			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
-			name=$(module_name "$sm_path")
+			name=$(git submodule--helper module_name "$sm_path")
 			(
 				prefix="$prefix$sm_path/"
 				clear_local_git_env
@@ -554,7 +536,7 @@ cmd_init()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -636,7 +618,7 @@ cmd_deinit()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -758,7 +740,7 @@ cmd_update()
 			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 			continue
 		fi
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		branch=$(get_submodule_config "$name" branch master)
 		if ! test -z "$update"
@@ -1022,7 +1004,7 @@ cmd_summary() {
 			# Respect the ignore setting for --for-status.
 			if test -n "$for_status"
 			then
-				name=$(module_name "$sm_path")
+				name=$(git submodule--helper module_name "$sm_path")
 				ignore_config=$(get_submodule_config "$name" ignore none)
 				test $status != A && test $ignore_config = all && continue
 			fi
@@ -1184,7 +1166,7 @@ cmd_status()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		displaypath=$(relative_path "$prefix$sm_path")
 		if test "$stage" = U
@@ -1261,7 +1243,7 @@ cmd_sync()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path")
+		name=$(git submodule--helper module_name "$sm_path")
 		url=$(git config -f .gitmodules --get submodule."$name".url)
 
 		# Possibly a url relative to parent
diff --git a/submodule.c b/submodule.c
index 15e90d1..78d7616 100644
--- a/submodule.c
+++ b/submodule.c
@@ -686,6 +686,16 @@ static void calculate_changed_submodule_paths(void)
 	initialized_fetch_ref_tips = 0;
 }
 
+const char *submodule_name_for_path(const char *path)
+{
+	struct string_list_item *item;
+	item = unsorted_string_list_lookup(&config_name_for_path, path);
+	if (!item)
+		return NULL;
+
+	return item->util;
+}
+
 int fetch_populated_submodules(const struct argv_array *options,
 			       const char *prefix, int command_line_option,
 			       int quiet)
@@ -693,7 +703,6 @@ int fetch_populated_submodules(const struct argv_array *options,
 	int i, result = 0;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	struct argv_array argv = ARGV_ARRAY_INIT;
-	struct string_list_item *name_for_path;
 	const char *work_tree = get_git_work_tree();
 	if (!work_tree)
 		goto out;
@@ -723,10 +732,10 @@ int fetch_populated_submodules(const struct argv_array *options,
 		if (!S_ISGITLINK(ce->ce_mode))
 			continue;
 
-		name = ce->name;
-		name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
-		if (name_for_path)
-			name = name_for_path->util;
+		name = submodule_name_for_path(ce->name);
+		if (!name)
+			/* Not in .gitmodules, try the default name == path */
+			name = ce->name;
 
 		default_argv = "yes";
 		if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
diff --git a/submodule.h b/submodule.h
index 7beec48..fc7f8a6 100644
--- a/submodule.h
+++ b/submodule.h
@@ -41,5 +41,6 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam
 		struct string_list *needs_pushing);
 int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
 void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
+const char *submodule_name_for_path(const char *path);
 
 #endif
-- 
2.5.0.239.g9728e1d.dirty

^ permalink raw reply related	[relevance 24%]

* Re: [PATCH 1/4] submodule: implement `module_list` as a builtin helper
  2015-08-05  0:04 19% [PATCH 1/4] submodule: implement `module_list` as a builtin helper Stefan Beller
  2015-08-05  0:04 23% ` [PATCH 2/4] submodule: implement `module_name` " Stefan Beller
  2015-08-05 18:31  6% ` [PATCH 1/4] submodule: implement `module_list` " Jens Lehmann
@ 2015-08-07 19:53  4% ` Junio C Hamano
  2 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-08-07 19:53 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, jens.lehmann, hvoigt

Stefan Beller <sbeller@google.com> writes:

> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> new file mode 100644
> index 0000000..cb18ddf
> --- /dev/null
> +++ b/builtin/submodule--helper.c
> @@ -0,0 +1,111 @@
> + ...
> +static char *ps_matched;
> +static const struct cache_entry **ce_entries;
> +static int ce_alloc, ce_used;
> +static struct pathspec pathspec;
> +static const char *alternative_path;

These are OK for now to be global variables, but in the longer run,
I think you would need to introduce a struct or two that group the
relevant pieces and passed around the callchain.  For example, a
caller calling into module_list_compute() would want to pass a
pointer to a struct that has ce_entries[] and ps_matched to receive
the result.  pathspec and alternative_path would want to be a
function-scope auto variable in module_list, I would think.

> +static void module_list_compute(int argc, const char **argv,
> +				const char *prefix,
> +				struct pathspec *pathspec)
> +{
> +	int i;
> +	char *max_prefix;
> +	int max_prefix_len;
> +	parse_pathspec(pathspec, 0,
> +		       PATHSPEC_PREFER_FULL |
> +		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
> +		       prefix, argv);
> +
> +	/* Find common prefix for all pathspec's */
> +	max_prefix = common_prefix(pathspec);
> +	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
> +
> +	if (pathspec->nr)
> +		ps_matched = xcalloc(1, pathspec->nr);
> +
> +
> +	if (read_cache() < 0)
> +		die("index file corrupt");

Again, this is OK for now, but I suspect you would eventually want
to return an error and have the caller react to it.

> +static int module_list(int argc, const char **argv, const char *prefix)
> +{
> +...
> +	for (i = 0; i < ce_used; i++) {
> +		const struct cache_entry *ce = ce_entries[i];
> +
> +		if (string_list_has_string(&already_printed, ce->name))
> +			continue;
> +
> +		if (ce_stage(ce)) {
> +			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
> +		} else {
> +			printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce));
> +		}
> +
> +		utf8_fprintf(stdout, "%s\n", ce->name);
> +
> +		string_list_insert(&already_printed, ce->name);

This looks a wasteful use of string-list.

When we iterate over the in-core index, or a subset obtained from
the in-core index without reordering, the standard technique to
handle entries for the same path only once is to handle one (while
remembering what it is) and then skip the ones that follow with the
same name, with a loop like this:

	i = 0;
        while (i < ce_used) {
        	ce = ce_entries[i++];
		use that ce;
                while (i < ce_used && !strcmp(ce->ce_name, ce_entries[i]->ce_name))
			i++; /* skip entries with the same name */
	}

Take advantage of the fact that the entries are still sorted.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-06 21:38 24%           ` Stefan Beller
@ 2015-08-07 20:03  7%             ` Junio C Hamano
  2015-08-07 20:54  4%               ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-08-07 20:03 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jens.Lehmann, git, hvoigt

Stefan Beller <sbeller@google.com> writes:

> This incorporates the changes from Jens fixup! commit
> (which addresses all issues he pointed out).
>
> I agree this looks much cleaner. :)

The only thing I found somewhat questionable is where to call
gitmodules_config() from.  I think it is OK to do this at the
beginning of module_name(), at least for now, simply because the
other function module_list() does not need to.

When you rewrite sufficiently large parts of the scripted Porcelain
into C so that different pieces translated from the shell functions
directly call into each other, that may have to change, though.  I
do not think gitmodules_config() is designed to be called more than
once, and I expect module_name() would be called many times inside a
loop.

Other than that, this is a trivial refactoring (i.e. a new helper
function added to submodule.c can be used from an existing
open-coded logic in the same file, and then the same helper function
gains a new callsite in submodule--helper.c) that makes things
easier to read.

Thanks.

>  builtin/submodule--helper.c | 22 ++++++++++++++++++++++
>  git-submodule.sh            | 32 +++++++-------------------------
>  submodule.c                 | 19 ++++++++++++++-----
>  submodule.h                 |  1 +
>  4 files changed, 44 insertions(+), 30 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index cb18ddf..bc37b74 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -5,6 +5,8 @@
>  #include "pathspec.h"
>  #include "dir.h"
>  #include "utf8.h"
> +#include "submodule.h"
> +#include "string-list.h"
>  
>  static char *ps_matched;
>  static const struct cache_entry **ce_entries;
> @@ -98,6 +100,23 @@ static int module_list(int argc, const char **argv, const char *prefix)
>  	return 0;
>  }
>  
> +static int module_name(int argc, const char **argv, const char *prefix)
> +{
> +	const char *name;
> +
> +	if (argc != 1)
> +		usage("git submodule--helper module_name <path>\n");
> +
> +	gitmodules_config();
> +	name = submodule_name_for_path(argv[0]);
> +
> +	if (!name)
> +		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
> +
> +	printf("%s\n", name);
> +	return 0;
> +}
> +
>  int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>  {
>  	if (argc < 2)
> @@ -106,6 +125,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>  	if (!strcmp(argv[1], "module_list"))
>  		return module_list(argc - 1, argv + 1, prefix);
>  
> +	if (!strcmp(argv[1], "module_name"))
> +		return module_name(argc - 2, argv + 2, prefix);
> +
>  usage:
>  	usage("git submodule--helper module_list\n");
>  }
> diff --git a/git-submodule.sh b/git-submodule.sh
> index af9ecef..e6ff38d 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -178,24 +178,6 @@ get_submodule_config () {
>  	printf '%s' "${value:-$default}"
>  }
>  
> -
> -#
> -# Map submodule path to submodule name
> -#
> -# $1 = path
> -#
> -module_name()
> -{
> -	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
> -	sm_path="$1"
> -	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
> -	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
> -		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
> -	test -z "$name" &&
> -	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
> -	printf '%s\n' "$name"
> -}
> -
>  #
>  # Clone a submodule
>  #
> @@ -498,7 +480,7 @@ cmd_foreach()
>  		then
>  			displaypath=$(relative_path "$sm_path")
>  			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
> -			name=$(module_name "$sm_path")
> +			name=$(git submodule--helper module_name "$sm_path")
>  			(
>  				prefix="$prefix$sm_path/"
>  				clear_local_git_env
> @@ -554,7 +536,7 @@ cmd_init()
>  	while read mode sha1 stage sm_path
>  	do
>  		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>  
>  		displaypath=$(relative_path "$sm_path")
>  
> @@ -636,7 +618,7 @@ cmd_deinit()
>  	while read mode sha1 stage sm_path
>  	do
>  		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>  
>  		displaypath=$(relative_path "$sm_path")
>  
> @@ -758,7 +740,7 @@ cmd_update()
>  			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
>  			continue
>  		fi
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>  		url=$(git config submodule."$name".url)
>  		branch=$(get_submodule_config "$name" branch master)
>  		if ! test -z "$update"
> @@ -1022,7 +1004,7 @@ cmd_summary() {
>  			# Respect the ignore setting for --for-status.
>  			if test -n "$for_status"
>  			then
> -				name=$(module_name "$sm_path")
> +				name=$(git submodule--helper module_name "$sm_path")
>  				ignore_config=$(get_submodule_config "$name" ignore none)
>  				test $status != A && test $ignore_config = all && continue
>  			fi
> @@ -1184,7 +1166,7 @@ cmd_status()
>  	while read mode sha1 stage sm_path
>  	do
>  		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path") || exit
> +		name=$(git submodule--helper module_name "$sm_path") || exit
>  		url=$(git config submodule."$name".url)
>  		displaypath=$(relative_path "$prefix$sm_path")
>  		if test "$stage" = U
> @@ -1261,7 +1243,7 @@ cmd_sync()
>  	while read mode sha1 stage sm_path
>  	do
>  		die_if_unmatched "$mode"
> -		name=$(module_name "$sm_path")
> +		name=$(git submodule--helper module_name "$sm_path")
>  		url=$(git config -f .gitmodules --get submodule."$name".url)
>  
>  		# Possibly a url relative to parent
> diff --git a/submodule.c b/submodule.c
> index 15e90d1..78d7616 100644
> --- a/submodule.c
> +++ b/submodule.c
> @@ -686,6 +686,16 @@ static void calculate_changed_submodule_paths(void)
>  	initialized_fetch_ref_tips = 0;
>  }
>  
> +const char *submodule_name_for_path(const char *path)
> +{
> +	struct string_list_item *item;
> +	item = unsorted_string_list_lookup(&config_name_for_path, path);
> +	if (!item)
> +		return NULL;
> +
> +	return item->util;
> +}
> +
>  int fetch_populated_submodules(const struct argv_array *options,
>  			       const char *prefix, int command_line_option,
>  			       int quiet)
> @@ -693,7 +703,6 @@ int fetch_populated_submodules(const struct argv_array *options,
>  	int i, result = 0;
>  	struct child_process cp = CHILD_PROCESS_INIT;
>  	struct argv_array argv = ARGV_ARRAY_INIT;
> -	struct string_list_item *name_for_path;
>  	const char *work_tree = get_git_work_tree();
>  	if (!work_tree)
>  		goto out;
> @@ -723,10 +732,10 @@ int fetch_populated_submodules(const struct argv_array *options,
>  		if (!S_ISGITLINK(ce->ce_mode))
>  			continue;
>  
> -		name = ce->name;
> -		name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
> -		if (name_for_path)
> -			name = name_for_path->util;
> +		name = submodule_name_for_path(ce->name);
> +		if (!name)
> +			/* Not in .gitmodules, try the default name == path */
> +			name = ce->name;
>  
>  		default_argv = "yes";
>  		if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
> diff --git a/submodule.h b/submodule.h
> index 7beec48..fc7f8a6 100644
> --- a/submodule.h
> +++ b/submodule.h
> @@ -41,5 +41,6 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam
>  		struct string_list *needs_pushing);
>  int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
>  void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
> +const char *submodule_name_for_path(const char *path);
>  
>  #endif

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  @ 2015-08-07 20:49  7%             ` Stefan Beller
  2015-08-07 21:14  6%               ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-07 20:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

On Fri, Aug 7, 2015 at 1:17 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Jens Lehmann <Jens.Lehmann@web.de> writes:
>
> This change...
>
>>> @@ -723,10 +733,8 @@ int fetch_populated_submodules(const struct argv_array *options,
>>>              if (!S_ISGITLINK(ce->ce_mode))
>>>                      continue;
>>>
>>> -            name = ce->name;
>>> -            name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
>>> -            if (name_for_path)
>>> -                    name = name_for_path->util;
>>> +            name_for_path = submodule_name_for_path(ce->name);
>>> +            name =  name_for_path ? name_for_path : ce->name;
>
> ... interacts with Heiko's cached submodule config work that seems
> to have stalled.

We can drop that hunk as it only uses the new method
`submodule_name_for_path` but doesn't change functionality.
So if you want to keep Heikos work, I'll just resend the patch
without that hunk.

>
> I can discard the stalled topic and queue this one instead, asking
> Heiko to reroll his on top once this has stabilized, or if Stefan is
> really into revamping submodule now (which I hope is the case),
> perhaps Heiko's work can be rerolled by Stefan (with help from
> others, of course) as a prerequisite and then these changes can be
> built on top of it?

I am a bit overwhelmed as I am into git submodule for a few days now
and still have not a full&good understanding of the details.
So for now my plan looks like this:

1) rewrite the helpers in C (module_list, module_name and module_clone)
   These helper functions are useful for themselves as they speed up
   git submodule operations, but I have them on the plan as they are a
   pre requisite for rewriting `git submodule update`

2) Come up with a good thread pool abstraction
   (Started as "[RFC/PATCH 0/4] parallel fetch for submodules" )
   This abstraction (if done right) will allow us to use it in different places
   easily. I started it as part of "git fetch --recurse-submodules" because
   it is submodule related and reasonably sized

3) Rewrite `git submodule update` in C
  This will start out as a literal translation and once 2 is coming
along nicely,
  I want to add that thread pool capability to the C rewrite.

This plan still is huge to me, but a lot smaller than my initial
"rewrite the whole
git-submodule.sh in C".

Once the rewrite and parallelism is done, I may want to start adding new
features to the submodules, such as different "classes". Currently I think
each submodule would have a set of these classes or features, such that
you could clone a superproject with hints on the classes:

  git clone <url-to-super-project> --submodule-flags=basis,amiga-specific,ui

each of the flags would then include a specifc set of submodules, such
that after cloning the super project you have everything you need to build
the program with ui on amiga.






>

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 20:03  7%             ` Junio C Hamano
@ 2015-08-07 20:54  4%               ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-07 20:54 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jens Lehmann, git@vger.kernel.org, Heiko Voigt

On Fri, Aug 7, 2015 at 1:03 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> This incorporates the changes from Jens fixup! commit
>> (which addresses all issues he pointed out).
>>
>> I agree this looks much cleaner. :)
>
> The only thing I found somewhat questionable is where to call
> gitmodules_config() from.  I think it is OK to do this at the
> beginning of module_name(), at least for now, simply because the
> other function module_list() does not need to.
>
> When you rewrite sufficiently large parts of the scripted Porcelain
> into C so that different pieces translated from the shell functions
> directly call into each other, that may have to change, though.  I
> do not think gitmodules_config() is designed to be called more than
> once, and I expect module_name() would be called many times inside a
> loop.

I want to structure the each part rewritten as a reusable core part
and a wrapper which just sets up the environment (option parsing,
reading the index, configs).

In this patch you only see the latter part, the wrapper, because the
core part only consists of one line

    name = submodule_name_for_path(<input>);

so I did not want to wrap that into its own function. But when rewriting
piece of shell code, which originally called into module_name, I'd rather
use the one liner instead. (This doesn't quite follow the literal translation
strategy, but I think it may be appropriate here).

>
> Other than that, this is a trivial refactoring (i.e. a new helper
> function added to submodule.c can be used from an existing
> open-coded logic in the same file, and then the same helper function
> gains a new callsite in submodule--helper.c) that makes things
> easier to read.
>
> Thanks.
>
>>  builtin/submodule--helper.c | 22 ++++++++++++++++++++++
>>  git-submodule.sh            | 32 +++++++-------------------------
>>  submodule.c                 | 19 ++++++++++++++-----
>>  submodule.h                 |  1 +
>>  4 files changed, 44 insertions(+), 30 deletions(-)
>>
>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
>> index cb18ddf..bc37b74 100644
>> --- a/builtin/submodule--helper.c
>> +++ b/builtin/submodule--helper.c
>> @@ -5,6 +5,8 @@
>>  #include "pathspec.h"
>>  #include "dir.h"
>>  #include "utf8.h"
>> +#include "submodule.h"
>> +#include "string-list.h"
>>
>>  static char *ps_matched;
>>  static const struct cache_entry **ce_entries;
>> @@ -98,6 +100,23 @@ static int module_list(int argc, const char **argv, const char *prefix)
>>       return 0;
>>  }
>>
>> +static int module_name(int argc, const char **argv, const char *prefix)
>> +{
>> +     const char *name;
>> +
>> +     if (argc != 1)
>> +             usage("git submodule--helper module_name <path>\n");
>> +
>> +     gitmodules_config();
>> +     name = submodule_name_for_path(argv[0]);
>> +
>> +     if (!name)
>> +             die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
>> +
>> +     printf("%s\n", name);
>> +     return 0;
>> +}
>> +
>>  int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>>  {
>>       if (argc < 2)
>> @@ -106,6 +125,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>>       if (!strcmp(argv[1], "module_list"))
>>               return module_list(argc - 1, argv + 1, prefix);
>>
>> +     if (!strcmp(argv[1], "module_name"))
>> +             return module_name(argc - 2, argv + 2, prefix);
>> +
>>  usage:
>>       usage("git submodule--helper module_list\n");
>>  }
>> diff --git a/git-submodule.sh b/git-submodule.sh
>> index af9ecef..e6ff38d 100755
>> --- a/git-submodule.sh
>> +++ b/git-submodule.sh
>> @@ -178,24 +178,6 @@ get_submodule_config () {
>>       printf '%s' "${value:-$default}"
>>  }
>>
>> -
>> -#
>> -# Map submodule path to submodule name
>> -#
>> -# $1 = path
>> -#
>> -module_name()
>> -{
>> -     # Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
>> -     sm_path="$1"
>> -     re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
>> -     name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
>> -             sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
>> -     test -z "$name" &&
>> -     die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
>> -     printf '%s\n' "$name"
>> -}
>> -
>>  #
>>  # Clone a submodule
>>  #
>> @@ -498,7 +480,7 @@ cmd_foreach()
>>               then
>>                       displaypath=$(relative_path "$sm_path")
>>                       say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
>> -                     name=$(module_name "$sm_path")
>> +                     name=$(git submodule--helper module_name "$sm_path")
>>                       (
>>                               prefix="$prefix$sm_path/"
>>                               clear_local_git_env
>> @@ -554,7 +536,7 @@ cmd_init()
>>       while read mode sha1 stage sm_path
>>       do
>>               die_if_unmatched "$mode"
>> -             name=$(module_name "$sm_path") || exit
>> +             name=$(git submodule--helper module_name "$sm_path") || exit
>>
>>               displaypath=$(relative_path "$sm_path")
>>
>> @@ -636,7 +618,7 @@ cmd_deinit()
>>       while read mode sha1 stage sm_path
>>       do
>>               die_if_unmatched "$mode"
>> -             name=$(module_name "$sm_path") || exit
>> +             name=$(git submodule--helper module_name "$sm_path") || exit
>>
>>               displaypath=$(relative_path "$sm_path")
>>
>> @@ -758,7 +740,7 @@ cmd_update()
>>                       echo >&2 "Skipping unmerged submodule $prefix$sm_path"
>>                       continue
>>               fi
>> -             name=$(module_name "$sm_path") || exit
>> +             name=$(git submodule--helper module_name "$sm_path") || exit
>>               url=$(git config submodule."$name".url)
>>               branch=$(get_submodule_config "$name" branch master)
>>               if ! test -z "$update"
>> @@ -1022,7 +1004,7 @@ cmd_summary() {
>>                       # Respect the ignore setting for --for-status.
>>                       if test -n "$for_status"
>>                       then
>> -                             name=$(module_name "$sm_path")
>> +                             name=$(git submodule--helper module_name "$sm_path")
>>                               ignore_config=$(get_submodule_config "$name" ignore none)
>>                               test $status != A && test $ignore_config = all && continue
>>                       fi
>> @@ -1184,7 +1166,7 @@ cmd_status()
>>       while read mode sha1 stage sm_path
>>       do
>>               die_if_unmatched "$mode"
>> -             name=$(module_name "$sm_path") || exit
>> +             name=$(git submodule--helper module_name "$sm_path") || exit
>>               url=$(git config submodule."$name".url)
>>               displaypath=$(relative_path "$prefix$sm_path")
>>               if test "$stage" = U
>> @@ -1261,7 +1243,7 @@ cmd_sync()
>>       while read mode sha1 stage sm_path
>>       do
>>               die_if_unmatched "$mode"
>> -             name=$(module_name "$sm_path")
>> +             name=$(git submodule--helper module_name "$sm_path")
>>               url=$(git config -f .gitmodules --get submodule."$name".url)
>>
>>               # Possibly a url relative to parent
>> diff --git a/submodule.c b/submodule.c
>> index 15e90d1..78d7616 100644
>> --- a/submodule.c
>> +++ b/submodule.c
>> @@ -686,6 +686,16 @@ static void calculate_changed_submodule_paths(void)
>>       initialized_fetch_ref_tips = 0;
>>  }
>>
>> +const char *submodule_name_for_path(const char *path)
>> +{
>> +     struct string_list_item *item;
>> +     item = unsorted_string_list_lookup(&config_name_for_path, path);
>> +     if (!item)
>> +             return NULL;
>> +
>> +     return item->util;
>> +}
>> +
>>  int fetch_populated_submodules(const struct argv_array *options,
>>                              const char *prefix, int command_line_option,
>>                              int quiet)
>> @@ -693,7 +703,6 @@ int fetch_populated_submodules(const struct argv_array *options,
>>       int i, result = 0;
>>       struct child_process cp = CHILD_PROCESS_INIT;
>>       struct argv_array argv = ARGV_ARRAY_INIT;
>> -     struct string_list_item *name_for_path;
>>       const char *work_tree = get_git_work_tree();
>>       if (!work_tree)
>>               goto out;
>> @@ -723,10 +732,10 @@ int fetch_populated_submodules(const struct argv_array *options,
>>               if (!S_ISGITLINK(ce->ce_mode))
>>                       continue;
>>
>> -             name = ce->name;
>> -             name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
>> -             if (name_for_path)
>> -                     name = name_for_path->util;
>> +             name = submodule_name_for_path(ce->name);
>> +             if (!name)
>> +                     /* Not in .gitmodules, try the default name == path */
>> +                     name = ce->name;
>>
>>               default_argv = "yes";
>>               if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
>> diff --git a/submodule.h b/submodule.h
>> index 7beec48..fc7f8a6 100644
>> --- a/submodule.h
>> +++ b/submodule.h
>> @@ -41,5 +41,6 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam
>>               struct string_list *needs_pushing);
>>  int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
>>  void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
>> +const char *submodule_name_for_path(const char *path);
>>
>>  #endif

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 20:49  7%             ` Stefan Beller
@ 2015-08-07 21:14  6%               ` Junio C Hamano
  2015-08-07 21:21  7%                 ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-08-07 21:14 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

Stefan Beller <sbeller@google.com> writes:

> On Fri, Aug 7, 2015 at 1:17 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Jens Lehmann <Jens.Lehmann@web.de> writes:
>>
>> This change...
>>
>>>> @@ -723,10 +733,8 @@ int fetch_populated_submodules(const struct argv_array *options,
>>>>              if (!S_ISGITLINK(ce->ce_mode))
>>>>                      continue;
>>>>
>>>> -            name = ce->name;
>>>> -            name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
>>>> -            if (name_for_path)
>>>> -                    name = name_for_path->util;
>>>> +            name_for_path = submodule_name_for_path(ce->name);
>>>> +            name =  name_for_path ? name_for_path : ce->name;
>>
>> ... interacts with Heiko's cached submodule config work that seems
>> to have stalled.
>
> We can drop that hunk as it only uses the new method
> `submodule_name_for_path` but doesn't change functionality.
> So if you want to keep Heikos work, I'll just resend the patch
> without that hunk.

Does such a result even make sense?  Note that I wasn't talking
about textual conflict.

If we followed what you just said, that patch will try to directly
read the data in config_name_for_path string list, which is removed
by Heiko's series, if I am reading it right.

In the new world order with Heiko's series, the way you grab
submodule configuration data is to call submodule_from_path() or
submodule_from_name() and they allow you to read from .gitmodules
either in a commit (for historical state), the index, or from the
working tree.  Which should be much cleaner and goes in the right
direction in the longer term.

And the best part of the story is that your module_name would be
just calling submodule_from_path() and peeking into a field.

> 2) Come up with a good thread pool abstraction
>    (Started as "[RFC/PATCH 0/4] parallel fetch for submodules" )
>    This abstraction (if done right) will allow us to use it in different places
>    easily. I started it as part of "git fetch --recurse-submodules" because
>    it is submodule related and reasonably sized

I personally think this gives the most bang-for-buck.  Write that
and expose it as "git submodule for-each-parallel", which takes the
shell scriptlet that currently is the loop body of "while read mode
sha1 stage sm_path" in update and clone.  You will have immediate
and large payback.

And you do not even need module_list and module_name written in C in
order to do so.  Not that these two are not trivial to implement, but
the payoff from them is not as large as from for-each-parallel ;-)

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 21:14  6%               ` Junio C Hamano
@ 2015-08-07 21:21  7%                 ` Stefan Beller
  2015-08-07 21:32  4%                   ` Junio C Hamano
  2015-08-07 22:42  7%                   ` Junio C Hamano
  0 siblings, 2 replies; 200+ results
From: Stefan Beller @ 2015-08-07 21:21 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

On Fri, Aug 7, 2015 at 2:14 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> On Fri, Aug 7, 2015 at 1:17 PM, Junio C Hamano <gitster@pobox.com> wrote:
>>> Jens Lehmann <Jens.Lehmann@web.de> writes:
>>>
>>> This change...
>>>
>>>>> @@ -723,10 +733,8 @@ int fetch_populated_submodules(const struct argv_array *options,
>>>>>              if (!S_ISGITLINK(ce->ce_mode))
>>>>>                      continue;
>>>>>
>>>>> -            name = ce->name;
>>>>> -            name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
>>>>> -            if (name_for_path)
>>>>> -                    name = name_for_path->util;
>>>>> +            name_for_path = submodule_name_for_path(ce->name);
>>>>> +            name =  name_for_path ? name_for_path : ce->name;
>>>
>>> ... interacts with Heiko's cached submodule config work that seems
>>> to have stalled.
>>
>> We can drop that hunk as it only uses the new method
>> `submodule_name_for_path` but doesn't change functionality.
>> So if you want to keep Heikos work, I'll just resend the patch
>> without that hunk.
>
> Does such a result even make sense?  Note that I wasn't talking
> about textual conflict.
>
> If we followed what you just said, that patch will try to directly
> read the data in config_name_for_path string list, which is removed
> by Heiko's series, if I am reading it right.
>
> In the new world order with Heiko's series, the way you grab
> submodule configuration data is to call submodule_from_path() or
> submodule_from_name() and they allow you to read from .gitmodules
> either in a commit (for historical state), the index, or from the
> working tree.  Which should be much cleaner and goes in the right
> direction in the longer term.
>
> And the best part of the story is that your module_name would be
> just calling submodule_from_path() and peeking into a field.
>
>> 2) Come up with a good thread pool abstraction
>>    (Started as "[RFC/PATCH 0/4] parallel fetch for submodules" )
>>    This abstraction (if done right) will allow us to use it in different places
>>    easily. I started it as part of "git fetch --recurse-submodules" because
>>    it is submodule related and reasonably sized
>
> I personally think this gives the most bang-for-buck.  Write that
> and expose it as "git submodule for-each-parallel", which takes the
> shell scriptlet that currently is the loop body of "while read mode
> sha1 stage sm_path" in update and clone.  You will have immediate
> and large payback.

You said that before. I feel like this is a bit to narrow. A "git submodule
for-each-parallel" would be a very specific tool which we would use to
make the different submodule operations parallel with ease. But it would
be very submodule specifc I guess?

That's why I want to be a bit more generic and have this thread pool API
done in C, such that "any for loop" in git can be easily replaced by using
the thread pool. I think of "git fetch --all" specially.

>
> And you do not even need module_list and module_name written in C in
> order to do so.  Not that these two are not trivial to implement, but
> the payoff from them is not as large as from for-each-parallel ;-)
>

I think I can do this for-each-parallel once I have the more generic thread
pooling done. All that is left now is a good handling of stdout/stderr, which
I am not yet convinced how to do it right. Maybe each task accumulates
messages in two string buffers and then the thread pool will output the
string buffer one a task is done.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 21:21  7%                 ` Stefan Beller
@ 2015-08-07 21:32  4%                   ` Junio C Hamano
  2015-08-07 22:04  7%                     ` Stefan Beller
  2015-08-07 22:42  7%                   ` Junio C Hamano
  1 sibling, 1 reply; 200+ results
From: Junio C Hamano @ 2015-08-07 21:32 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

Stefan Beller <sbeller@google.com> writes:

> On Fri, Aug 7, 2015 at 2:14 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Stefan Beller <sbeller@google.com> writes:
>>> ...
>>> We can drop that hunk as it only uses the new method
>>> `submodule_name_for_path` but doesn't change functionality.
>>> So if you want to keep Heikos work, I'll just resend the patch
>>> without that hunk.
>>
>> Does such a result even make sense?  Note that I wasn't talking
>> about textual conflict.
>>
>> If we followed what you just said, that patch will try to directly
>> read the data in config_name_for_path string list, which is removed
>> by Heiko's series, if I am reading it right.

By the way, the above is more important part of the message you are
responding to.  The result does not simply link, because your
unsorted_string_list_lookup() will no longer have the string list in
the first place X-<.

>>> 2) Come up with a good thread pool abstraction
>>>    (Started as "[RFC/PATCH 0/4] parallel fetch for submodules" )
>>>    This abstraction (if done right) will allow us to use it in different places
>>>    easily. I started it as part of "git fetch --recurse-submodules" because
>>>    it is submodule related and reasonably sized
>>
>> I personally think this gives the most bang-for-buck.  Write that
>> and expose it as "git submodule for-each-parallel", which takes the
>> shell scriptlet that currently is the loop body of "while read mode
>> sha1 stage sm_path" in update and clone.  You will have immediate
>> and large payback.
>
> You said that before. I feel like this is a bit to narrow.

That depends on how good a design you make for the internal
"parallel execution" engine.  If it is made to take an arbitrary C
function with list of arguments to call it with, for-each-parallel
would be just a degenerate and narrow case where that arbitrary C
function happens to be exec'ing a shell and feed a shell scriptlet
to it.

The internal parallel execution engine would be reusable without any
change to call C native functions, allowing you to do everything
inside the process in the future.  And the "narrow" case is a good
first step to validate your design actually _works_.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 21:32  4%                   ` Junio C Hamano
@ 2015-08-07 22:04  7%                     ` Stefan Beller
  2015-08-07 22:18  4%                       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-07 22:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

On Fri, Aug 7, 2015 at 2:32 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> On Fri, Aug 7, 2015 at 2:14 PM, Junio C Hamano <gitster@pobox.com> wrote:
>>> Stefan Beller <sbeller@google.com> writes:
>>>> ...
>>>> We can drop that hunk as it only uses the new method
>>>> `submodule_name_for_path` but doesn't change functionality.
>>>> So if you want to keep Heikos work, I'll just resend the patch
>>>> without that hunk.
>>>
>>> Does such a result even make sense?  Note that I wasn't talking
>>> about textual conflict.
>>>
>>> If we followed what you just said, that patch will try to directly
>>> read the data in config_name_for_path string list, which is removed
>>> by Heiko's series, if I am reading it right.
>
> By the way, the above is more important part of the message you are
> responding to.  The result does not simply link, because your
> unsorted_string_list_lookup() will no longer have the string list in
> the first place X-<.

I looked through Heikos series and think it is an improvement. I mean I
can redo my patches on top of his. Specially this patch will be easy,
as patch 2/4 (extract functions for submodule config set and lookup)
implements get_name_for_path. All I would need to do then is expose it
to the shell via the helper.

>
>>>> 2) Come up with a good thread pool abstraction
>>>>    (Started as "[RFC/PATCH 0/4] parallel fetch for submodules" )
>>>>    This abstraction (if done right) will allow us to use it in different places
>>>>    easily. I started it as part of "git fetch --recurse-submodules" because
>>>>    it is submodule related and reasonably sized
>>>
>>> I personally think this gives the most bang-for-buck.  Write that
>>> and expose it as "git submodule for-each-parallel", which takes the
>>> shell scriptlet that currently is the loop body of "while read mode
>>> sha1 stage sm_path" in update and clone.  You will have immediate
>>> and large payback.
>>
>> You said that before. I feel like this is a bit to narrow.
>
> That depends on how good a design you make for the internal
> "parallel execution" engine.  If it is made to take an arbitrary C
> function with list of arguments to call it with, for-each-parallel
> would be just a degenerate and narrow case where that arbitrary C
> function happens to be exec'ing a shell and feed a shell scriptlet
> to it.
>
> The internal parallel execution engine would be reusable without any
> change to call C native functions, allowing you to do everything
> inside the process in the future.  And the "narrow" case is a good
> first step to validate your design actually _works_.
>

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 22:04  7%                     ` Stefan Beller
@ 2015-08-07 22:18  4%                       ` Junio C Hamano
  2015-08-07 23:12  4%                         ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-08-07 22:18 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

Stefan Beller <sbeller@google.com> writes:

> On Fri, Aug 7, 2015 at 2:32 PM, Junio C Hamano <gitster@pobox.com> wrote:
>
>>>> If we followed what you just said, that patch will try to directly
>>>> read the data in config_name_for_path string list, which is removed
>>>> by Heiko's series, if I am reading it right.
>>
>> By the way, the above is more important part of the message you are
>> responding to.  The result does not simply link, because your
>> unsorted_string_list_lookup() will no longer have the string list in
>> the first place X-<.
>
> I looked through Heikos series and think it is an improvement. I mean I
> can redo my patches on top of his. Specially this patch will be easy,
> as patch 2/4 (extract functions for submodule config set and lookup)
> implements get_name_for_path. All I would need to do then is expose it
> to the shell via the helper.

Yes, that is exactly what I said a few messages ago, wasn't it?

But that would require that you read and understand Heiko's work and
that you understand what its future direction should be, communicate
that vision to others to share, before building on top of it.  And
with that effort, you would already be in a good position to polish
Heiko's stalled work and move it forward.  After all, you cannot
just build on a stalled work, declare "my part is done; the result
is not mergeable because the foundation is not cooked, but that is
not my problem" ;-).

IIRC, the issues around the topic were nothing show-stopping, but
the primary reason it stalled was that Heiko got busy with his other
obligations, so I'd appreciate others like you to help the topic
move forward.

Thanks.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 21:21  7%                 ` Stefan Beller
  2015-08-07 21:32  4%                   ` Junio C Hamano
@ 2015-08-07 22:42  7%                   ` Junio C Hamano
  2015-08-07 23:19  7%                     ` Stefan Beller
  1 sibling, 1 reply; 200+ results
From: Junio C Hamano @ 2015-08-07 22:42 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

Stefan Beller <sbeller@google.com> writes:

> That's why I want to be a bit more generic and have this thread pool API
> done in C, such that "any for loop" in git can be easily replaced by using
> the thread pool. I think of "git fetch --all" specially.

One more thing, as I didn't notice that you kept repeating "thread"
pool API.

While I doubt that you would gain much by using threads in place of
processes to perform parallel "submodule update", "submodule clone",
"fetch all", etc., all of which are fairly well isolated and heavy
weight operations themselves, and I suspect that the implementation
simplicity of using separate processes would probably be huge plus
compared to any possible upside you may gain from using threads, if
you really want to go the "thread" route, the first thing to try
would be to see if a few places we already use threads for
parallelism (namely, "grep", "pack-objects", "preload-index" and
"index-pack") can be factored out and model your new API around the
commonality among them.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 22:18  4%                       ` Junio C Hamano
@ 2015-08-07 23:12  4%                         ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-07 23:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

On Fri, Aug 7, 2015 at 3:18 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> On Fri, Aug 7, 2015 at 2:32 PM, Junio C Hamano <gitster@pobox.com> wrote:
>>
>>>>> If we followed what you just said, that patch will try to directly
>>>>> read the data in config_name_for_path string list, which is removed
>>>>> by Heiko's series, if I am reading it right.
>>>
>>> By the way, the above is more important part of the message you are
>>> responding to.  The result does not simply link, because your
>>> unsorted_string_list_lookup() will no longer have the string list in
>>> the first place X-<.
>>
>> I looked through Heikos series and think it is an improvement. I mean I
>> can redo my patches on top of his. Specially this patch will be easy,
>> as patch 2/4 (extract functions for submodule config set and lookup)
>> implements get_name_for_path. All I would need to do then is expose it
>> to the shell via the helper.
>
> Yes, that is exactly what I said a few messages ago, wasn't it?

Yes, you did. I needed to repeat it to actually mentally process it.

>
> But that would require that you read and understand Heiko's work and
> that you understand what its future direction should be, communicate
> that vision to others to share, before building on top of it.  And
> with that effort, you would already be in a good position to polish
> Heiko's stalled work and move it forward.  After all, you cannot
> just build on a stalled work, declare "my part is done; the result
> is not mergeable because the foundation is not cooked, but that is
> not my problem" ;-).

That would be an easy world to live in, but I agree that I should get the
fundamentals right.

>
> IIRC, the issues around the topic were nothing show-stopping, but
> the primary reason it stalled was that Heiko got busy with his other
> obligations, so I'd appreciate others like you to help the topic
> move forward.

Ok, I'll dig up the old reviews and review it myself before continuing
on my patches.

>
> Thanks.
>

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 22:42  7%                   ` Junio C Hamano
@ 2015-08-07 23:19  7%                     ` Stefan Beller
  2015-08-08  0:21  4%                       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-07 23:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

On Fri, Aug 7, 2015 at 3:42 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> That's why I want to be a bit more generic and have this thread pool API
>> done in C, such that "any for loop" in git can be easily replaced by using
>> the thread pool. I think of "git fetch --all" specially.
>
> One more thing, as I didn't notice that you kept repeating "thread"
> pool API.

Yeah I intended to use both threads and processes for the heavy submodule
operations.

Each thread in the thread pool would setup the right argument lists
and environment
and then spawn a process for heavy weight operations, wait for the process,
maybe process its output.

Maybe I should omit the whole thread pool and only use select from a single
threaded main program.

>
> While I doubt that you would gain much by using threads in place of
> processes to perform parallel "submodule update", "submodule clone",
> "fetch all", etc., all of which are fairly well isolated and heavy
> weight operations themselves, and I suspect that the implementation
> simplicity of using separate processes would probably be huge plus
> compared to any possible upside you may gain from using threads, if
> you really want to go the "thread" route, the first thing to try
> would be to see if a few places we already use threads for
> parallelism (namely, "grep", "pack-objects", "preload-index" and
> "index-pack") can be factored out and model your new API around the
> commonality among them.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  2015-08-07 23:19  7%                     ` Stefan Beller
@ 2015-08-08  0:21  4%                       ` Junio C Hamano
    0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2015-08-08  0:21 UTC (permalink / raw)
  To: Stefan Beller; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

Stefan Beller <sbeller@google.com> writes:

>> One more thing, as I didn't notice that you kept repeating "thread"
>> pool API.
>
> Yeah I intended to use both threads and processes for the heavy submodule
> operations.

OK.  I somehow had an impression that it might be more tricky than
it is worth to spawn/run_command out of a thread/run_async, but if
it makes it easier and more generic to correctly arrange the
thread-pool API to allow the per-thread functions to run_command(),
I wouldn't object to that approach at all.

Then for-each-parallel would truly become a trivial application of
that API.  Your per-thread function happens to be a one that
prepares appropriate "struct child_process" and calls run_command()
to interact with that single child, receiving its output and culling
it when it is done.

>> ... if
>> you really want to go the "thread" route, the first thing to try
>> would be to see if a few places we already use threads for
>> parallelism (namely, "grep", "pack-objects", "preload-index" and
>> "index-pack") can be factored out and model your new API around the
>> commonality among them.

And obviously, doing your pool API around threads will allow you to
throw future per-thread function that do not involve run_command()
at all at your API, and it will make it easy to adapt the current
threaded parts of the system to the API.

Perfect.

;-)

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] submodule: implement `module_name` as a builtin helper
  @ 2015-08-10 17:03  7%                           ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-10 17:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jens Lehmann, Heiko Voigt, git@vger.kernel.org

On Fri, Aug 7, 2015 at 11:20 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
>>>> ... if
>>>> you really want to go the "thread" route, the first thing to try
>>>> would be to see if a few places we already use threads for
>>>> parallelism (namely, "grep", "pack-objects", "preload-index" and
>>>> "index-pack") can be factored out and model your new API around the
>>>> commonality among them.
>>
>> And obviously, doing your pool API around threads will allow you to
>> throw future per-thread function that do not involve run_command()
>> at all at your API, and it will make it easy to adapt the current
>> threaded parts of the system to the API.
>
> Just a few random thoughts before going to bed and going offline for
> the weekend...
>
> Eventually, we would want to do "submodule update" of a top-level
> project that has 500 submodules underneath, but obviously we would
> not want to blindly spawn 500 threads, each of which runs "fetch",
> all at the same time.  We'd want to limit the parallelism to a sane
> limit (say, 16 or 32), stuff 500 work units to a queue, from which
> that many number of worker bees grab work unit one by one to process
> and then come back to ask for more work.

This is exactly what is currently implemented and works in patch
"[RFC PATCH 2/4] Add a workdispatcher to get work done in parallel"

>
> And we would eventually want to be able to do this even when these
> 500 submodules are spread across multiple levels of nested
> submodules (e.g. top-level may have 8 submodules, and they have 16
> nested subsubmodules each on average, each of which may have 4
> nested subsubsubmodules on average).  Specifying -j16 at the top
> level and apportioning the parallelism to recursive invoation of
> "submodule update" in such a way that the overall process is
> efficient and without waste would be a bit tricky.
>
> In such a nested submodule case, we may want to instead try to
> enumerate these 500 submodules upfront with unbounded parallelism

The problem here is we need to have finished cloning at least one top level
submodule before we can add any further sub-submodules into the work
queue. So if there are only 4 top level submodules we'd have a slow start.

If we have only one top level work queue, the deeper nesting levels
will not explode unbound, but eventually we will reach the 16 threads
and keep working with them, and once git submodule is ported to C
we don't need to have process invocations, but can rely on the just the
threading done right. And then we it should be rather easy to only use
one top level task queue.

> (e.g. the top-level will ask 4 worker bees to process immediate 8
> submodules, and they each spawn 4 worker bees to process their
> immediate 16 submodules, and so on---it is unbounded because we do
> not know upfront how deep the nesting is).
>
> Let's call that a recursive module_list.  You would want out of a
> recursive module_list:
>
>  - the path to the submodule (or "." for the top-level) to indicate
>    where in the nested hierarchy the information came from;
>
>  - the information the flat module_list gives for that location.

I only see value in this recursive module_list approach for updating
the work tree (fetch --recurse-submodules=yes, instead of cloning)
as you already have most of the submodules there (there may be new
submodules after fetching).

Also collecting 500 submodule information is in the order of reading
500 files. But then we need to do 500 fetches. And doing a fetch takes
some orders of magnitude longer than reading a file, so I am not convinced
a parallel collection of work to be done is a good first step?

>
> Since you already have module_list() function natively callable from
> C and also it is available via "git submodule--helper module_list",
> implementing a recursive module_list would be a good first proof of
> concept exercise for your "thread pool" engine.  You can employ the
> "dual implementation" trick to call
>
>  - a version that tells the thread to run the native C version of
>    module_list(),
>
>  - another version that tells the thread to run_command()
>    "submodule--helper module_list" in the top-level and nested
>    submodules.
>
> and collect and compare their results and performance.
>
> That will not just be a good proof of concept for the pool
> implementation.
>
> Once you have such a recursive module_list, you can use it as a way
> to easily obtain such a "unified view" list of all submodules.  That
> can be used to stuff a flat work unit queue to implement reasonably
> bounded parallelism.
>
> Your recursive "submoule update" implementation could be
>
>  - Run recursive module_list to stuff the work queue with these 500
>    submodules (possibly spread across in top-level and in nested
>    submodules, or all 500 in the flat top-level);
>
>  - Start N worker bees, and tell them to pick from that work queue,
>    each element of which tells them to process which submodule that
>    resides in where (either in the top-level project or in a
>    submodule).
>
> And each work element would essentially be to run "git fetch" in
> that submodule directory.

As said before the 500 fetches are many orders of magnitude slower than
collecting the information what to do.

>
> Hmm...
>
>

^ permalink raw reply	[relevance 7%]

* Re: [PATCH v5 0/4] submodule config lookup API
  @ 2015-08-10 19:23  7%   ` Stefan Beller
  2015-08-12 17:53  4%     ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-10 19:23 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Heiko Voigt, git@vger.kernel.org, Jens Lehmann, Jonathan Nieder,
	Jeff King, W. Trevor King, Eric Sunshine, Karsten Blees

On Mon, Jun 15, 2015 at 2:48 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Thanks.  Will replace and wait for comments from others.

I have reviewed the patches carefully and they look good to me.

As Git is a large project and I was active in other parts until now,
I noticed that there are subtle differences in style as when compared
to the refs code. One example would be the way comments are written.
In d378e35d256348f (Patch 1, implement submodule config API for
lookup of .gitmodules values) the comments for the data structures in
submodule-config.c seem to have a non exposed "headline" and if more
is needed proper sentences with capitalized starts and punctuation at the
end. In the refs code there are only sentences IIRC. Most of the commits
touching submodule.{c,h} do not prefix their commit message with
"submodule:"

The style is no show stopper of course, just an observation from someone
moving into a different area of code.

Thanks,
Stefan

^ permalink raw reply	[relevance 7%]

* Re: [PATCH v5 0/4] submodule config lookup API
  2015-08-10 19:23  7%   ` Stefan Beller
@ 2015-08-12 17:53  4%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-08-12 17:53 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Heiko Voigt, git@vger.kernel.org, Jens Lehmann, Jonathan Nieder,
	Jeff King, W. Trevor King, Eric Sunshine, Karsten Blees

Stefan Beller <sbeller@google.com> writes:

> On Mon, Jun 15, 2015 at 2:48 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Thanks.  Will replace and wait for comments from others.
>
> I have reviewed the patches carefully and they look good to me.

OK, I recall there were a few iterations with review comments before
this round.  Is it your impression that they have been addressed
adequately?

Do you prefer it to be rebased to a more recent 'master' before you
build your work on top of it (I think the topic currently builds on
top of v2.5.0-rc0~56)?

Thanks.

^ permalink raw reply	[relevance 4%]

* [PATCH 1/2] Fixup hv/documentation
  2015-08-12 19:13 10% [PATCH v5 0/4] submodule config lookup API Stefan Beller
@ 2015-08-12 19:13 20% ` Stefan Beller
  2015-08-12 19:13 22% ` [PATCH 2/2] cleanup submodule_config a bit Stefan Beller
  2015-08-12 19:27  4% ` [PATCH v5 0/4] submodule config lookup API Junio C Hamano
  2 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-12 19:13 UTC (permalink / raw)
  To: gitster
  Cc: hvoigt, git, jens.lehmann, jrnieder, peff, wking, sunshine,
	karsten.blees, Stefan Beller

If you want to look up by name, use `submodule_from_name` instead.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Documentation/technical/api-submodule-config.txt | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/Documentation/technical/api-submodule-config.txt b/Documentation/technical/api-submodule-config.txt
index 2ea520a..941fa17 100644
--- a/Documentation/technical/api-submodule-config.txt
+++ b/Documentation/technical/api-submodule-config.txt
@@ -49,8 +49,7 @@ Functions
 
 `const struct submodule *submodule_from_path(const unsigned char *commit_sha1, const char *path)`::
 
-	Lookup values for one submodule by its commit_sha1 and path or
-	name.
+	Lookup values for one submodule by its commit_sha1 and path.
 
 `const struct submodule *submodule_from_name(const unsigned char *commit_sha1, const char *name)`::
 
-- 
2.5.0.234.gefc8a62

^ permalink raw reply related	[relevance 20%]

* Re: [PATCH v5 0/4] submodule config lookup API
@ 2015-08-12 19:13 10% Stefan Beller
  2015-08-12 19:13 20% ` [PATCH 1/2] Fixup hv/documentation Stefan Beller
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Stefan Beller @ 2015-08-12 19:13 UTC (permalink / raw)
  To: gitster
  Cc: hvoigt, git, jens.lehmann, jrnieder, peff, wking, sunshine,
	karsten.blees, Stefan Beller

On Wed, Aug 12, 2015 at 10:53 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> On Mon, Jun 15, 2015 at 2:48 PM, Junio C Hamano <gitster@pobox.com> wrote:
>>> Thanks.  Will replace and wait for comments from others.
>>
>> I have reviewed the patches carefully and they look good to me.
>
> OK, I recall there were a few iterations with review comments before
> this round.  Is it your impression that they have been addressed
> adequately?

I payed only little attention to the previous rounds and the review comments
thereof, because round 5 was up for quite a long time and nobody commented so far.

However just as I was convinced of my review and sent out the email, I started
working with it. And I found nits which I'd ask you to squash into the round or
put on top.

>
> Do you prefer it to be rebased to a more recent 'master' before you
> build your work on top of it (I think the topic currently builds on
> top of v2.5.0-rc0~56)?

Looking at the reviews for the "RFC parallel fetch for submodules"
I'd like to use `argv_array_pushv` which was introduced via
85b343245b (2015-06-14, argv-array: implement argv_array_pushv())
and is already in origin/next, but not origin/master.
But as I first work on the submodule--helper (both the small helper
functions as well as the whole "update" thereafter), I think this
dependency is not a pressing issue yet.

>
> Thanks.

Stefan Beller (2):
  Fixup hv/documentation
  cleanup submodule_config a bit.

 Documentation/technical/api-submodule-config.txt |  3 +--
 submodule-config.c                               | 12 +++++-------
 2 files changed, 6 insertions(+), 9 deletions(-)

-- 
2.5.0.234.gefc8a62

^ permalink raw reply	[relevance 10%]

* [PATCH 2/2] cleanup submodule_config a bit.
  2015-08-12 19:13 10% [PATCH v5 0/4] submodule config lookup API Stefan Beller
  2015-08-12 19:13 20% ` [PATCH 1/2] Fixup hv/documentation Stefan Beller
@ 2015-08-12 19:13 22% ` Stefan Beller
  2015-08-12 21:13  4%   ` Eric Sunshine
  2015-08-12 19:27  4% ` [PATCH v5 0/4] submodule config lookup API Junio C Hamano
  2 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-12 19:13 UTC (permalink / raw)
  To: gitster
  Cc: hvoigt, git, jens.lehmann, jrnieder, peff, wking, sunshine,
	karsten.blees, Stefan Beller

In the first hunk, `submodule` is NULL all the time, so we can make it clearer
by directly returning NULL.

In the second hunk, we can directly return the lookup values as it also makes
the coder clearer.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 submodule-config.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/submodule-config.c b/submodule-config.c
index 199692b..08e93cc 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -387,7 +387,7 @@ static const struct submodule *config_from(struct submodule_cache *cache,
 	}
 
 	if (!gitmodule_sha1_from_commit(commit_sha1, sha1))
-		return submodule;
+		return NULL;
 
 	switch (lookup_type) {
 	case lookup_name:
@@ -420,14 +420,12 @@ static const struct submodule *config_from(struct submodule_cache *cache,
 
 	switch (lookup_type) {
 	case lookup_name:
-		submodule = cache_lookup_name(cache, sha1, key);
-		break;
+		return cache_lookup_name(cache, sha1, key);
 	case lookup_path:
-		submodule = cache_lookup_path(cache, sha1, key);
-		break;
+		return cache_lookup_path(cache, sha1, key);
+	default:
+		return NULL;
 	}
-
-	return submodule;
 }
 
 static const struct submodule *config_from_path(struct submodule_cache *cache,
-- 
2.5.0.234.gefc8a62

^ permalink raw reply related	[relevance 22%]

* Re: [PATCH v5 0/4] submodule config lookup API
  2015-08-12 19:13 10% [PATCH v5 0/4] submodule config lookup API Stefan Beller
  2015-08-12 19:13 20% ` [PATCH 1/2] Fixup hv/documentation Stefan Beller
  2015-08-12 19:13 22% ` [PATCH 2/2] cleanup submodule_config a bit Stefan Beller
@ 2015-08-12 19:27  4% ` Junio C Hamano
  2 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-08-12 19:27 UTC (permalink / raw)
  To: Stefan Beller
  Cc: hvoigt, git, jens.lehmann, jrnieder, peff, wking, sunshine,
	karsten.blees

Stefan Beller <sbeller@google.com> writes:

> However just as I was convinced of my review and sent out the email, I started
> working with it. And I found nits which I'd ask you to squash into the round or
> put on top.

Good ;-).  I'd prefer a full reroll, as it has been quite a while
since v5 was originally posted, once you get to a reasonable state
where you are reasonably confident that you won't find more of such
nits.  Hopefully more people might have eyes on the list to review
and comment this round.

Thanks.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH 2/2] cleanup submodule_config a bit.
  2015-08-12 19:13 22% ` [PATCH 2/2] cleanup submodule_config a bit Stefan Beller
@ 2015-08-12 21:13  4%   ` Eric Sunshine
  2015-08-12 21:34  4%     ` Stefan Beller
  0 siblings, 1 reply; 200+ results
From: Eric Sunshine @ 2015-08-12 21:13 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Junio C Hamano, Heiko Voigt, Git List, Jens Lehmann,
	Jonathan Nieder, Jeff King, W. Trevor King, Karsten Blees

On Wed, Aug 12, 2015 at 3:13 PM, Stefan Beller <sbeller@google.com> wrote:
> In the first hunk, `submodule` is NULL all the time, so we can make it clearer
> by directly returning NULL.
>
> In the second hunk, we can directly return the lookup values as it also makes
> the coder clearer.
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>  submodule-config.c | 12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/submodule-config.c b/submodule-config.c
> index 199692b..08e93cc 100644
> --- a/submodule-config.c
> +++ b/submodule-config.c
> @@ -387,7 +387,7 @@ static const struct submodule *config_from(struct submodule_cache *cache,
>         }
>
>         if (!gitmodule_sha1_from_commit(commit_sha1, sha1))
> -               return submodule;
> +               return NULL;

There are a couple other places which return 'submodule' when it is
known to be NULL. One could rightly expect that they deserve the same
treatment, otherwise, the code becomes more confusing since it's not
obvious why 'return NULL' is used some places but not others.

>         switch (lookup_type) {
>         case lookup_name:
> @@ -420,14 +420,12 @@ static const struct submodule *config_from(struct submodule_cache *cache,
>
>         switch (lookup_type) {
>         case lookup_name:
> -               submodule = cache_lookup_name(cache, sha1, key);
> -               break;
> +               return cache_lookup_name(cache, sha1, key);
>         case lookup_path:
> -               submodule = cache_lookup_path(cache, sha1, key);
> -               break;
> +               return cache_lookup_path(cache, sha1, key);
> +       default:
> +               return NULL;
>         }
> -
> -       return submodule;

Earlier in the function, there's effectively a clone of this logic to
which you could apply the same transformation. Changing it here, while
ignoring the clone, makes the code more confusing (or at least
inconsistent) rather than less.

>  }
>
>  static const struct submodule *config_from_path(struct submodule_cache *cache,
> --
> 2.5.0.234.gefc8a62

^ permalink raw reply	[relevance 4%]

* Re: [PATCH 2/2] cleanup submodule_config a bit.
  2015-08-12 21:13  4%   ` Eric Sunshine
@ 2015-08-12 21:34  4%     ` Stefan Beller
  2015-08-12 22:01  2%       ` Eric Sunshine
  0 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-12 21:34 UTC (permalink / raw)
  To: Eric Sunshine
  Cc: Junio C Hamano, Heiko Voigt, Git List, Jens Lehmann,
	Jonathan Nieder, Jeff King, W. Trevor King, Karsten Blees

On Wed, Aug 12, 2015 at 2:13 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:
> On Wed, Aug 12, 2015 at 3:13 PM, Stefan Beller <sbeller@google.com> wrote:
>> In the first hunk, `submodule` is NULL all the time, so we can make it clearer
>> by directly returning NULL.
>>
>> In the second hunk, we can directly return the lookup values as it also makes
>> the coder clearer.
>>
>> Signed-off-by: Stefan Beller <sbeller@google.com>
>> ---
>>  submodule-config.c | 12 +++++-------
>>  1 file changed, 5 insertions(+), 7 deletions(-)
>>
>> diff --git a/submodule-config.c b/submodule-config.c
>> index 199692b..08e93cc 100644
>> --- a/submodule-config.c
>> +++ b/submodule-config.c
>> @@ -387,7 +387,7 @@ static const struct submodule *config_from(struct submodule_cache *cache,
>>         }
>>
>>         if (!gitmodule_sha1_from_commit(commit_sha1, sha1))
>> -               return submodule;
>> +               return NULL;
>
> There are a couple other places which return 'submodule' when it is
> known to be NULL. One could rightly expect that they deserve the same
> treatment, otherwise, the code becomes more confusing since it's not
> obvious why 'return NULL' is used some places but not others.

They were slightly less obvious to me, fixed now as well!

>
>>         switch (lookup_type) {
>>         case lookup_name:
>> @@ -420,14 +420,12 @@ static const struct submodule *config_from(struct submodule_cache *cache,
>>
>>         switch (lookup_type) {
>>         case lookup_name:
>> -               submodule = cache_lookup_name(cache, sha1, key);
>> -               break;
>> +               return cache_lookup_name(cache, sha1, key);
>>         case lookup_path:
>> -               submodule = cache_lookup_path(cache, sha1, key);
>> -               break;
>> +               return cache_lookup_path(cache, sha1, key);
>> +       default:
>> +               return NULL;
>>         }
>> -
>> -       return submodule;
>
> Earlier in the function, there's effectively a clone of this logic to
> which you could apply the same transformation. Changing it here, while
> ignoring the clone, makes the code more confusing (or at least
> inconsistent) rather than less.

Not quite. Note the `if (submodule)` in the earlier version, so in case
cache_lookup_{name, path} return NULL, we keep going. The change I
propose is at the end of the function and we definitely return no matter
if it is NULL or not.

>
>>  }
>>
>>  static const struct submodule *config_from_path(struct submodule_cache *cache,
>> --
>> 2.5.0.234.gefc8a62

^ permalink raw reply	[relevance 4%]

* Re: [PATCH 2/2] cleanup submodule_config a bit.
  2015-08-12 21:34  4%     ` Stefan Beller
@ 2015-08-12 22:01  2%       ` Eric Sunshine
  0 siblings, 0 replies; 200+ results
From: Eric Sunshine @ 2015-08-12 22:01 UTC (permalink / raw)
  To: Stefan Beller
  Cc: Junio C Hamano, Heiko Voigt, Git List, Jens Lehmann,
	Jonathan Nieder, Jeff King, W. Trevor King, Karsten Blees

On Wed, Aug 12, 2015 at 5:34 PM, Stefan Beller <sbeller@google.com> wrote:
> On Wed, Aug 12, 2015 at 2:13 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:
>> On Wed, Aug 12, 2015 at 3:13 PM, Stefan Beller <sbeller@google.com> wrote:
>>>         if (!gitmodule_sha1_from_commit(commit_sha1, sha1))
>>> -               return submodule;
>>> +               return NULL;
>>
>> There are a couple other places which return 'submodule' when it is
>> known to be NULL. One could rightly expect that they deserve the same
>> treatment, otherwise, the code becomes more confusing since it's not
>> obvious why 'return NULL' is used some places but not others.
>
> They were slightly less obvious to me, fixed now as well!
>
>>> @@ -420,14 +420,12 @@ static const struct submodule *config_from(struct submodule_cache *cache,
>>>         switch (lookup_type) {
>>>         case lookup_name:
>>> -               submodule = cache_lookup_name(cache, sha1, key);
>>> -               break;
>>> +               return cache_lookup_name(cache, sha1, key);
>>>         case lookup_path:
>>> -               submodule = cache_lookup_path(cache, sha1, key);
>>> -               break;
>>> +               return cache_lookup_path(cache, sha1, key);
>>> +       default:
>>> +               return NULL;
>>>         }
>>> -
>>> -       return submodule;
>>
>> Earlier in the function, there's effectively a clone of this logic to
>> which you could apply the same transformation. Changing it here, while
>> ignoring the clone, makes the code more confusing (or at least
>> inconsistent) rather than less.
>
> Not quite. Note the `if (submodule)` in the earlier version, so in case
> cache_lookup_{name, path} return NULL, we keep going. The change I
> propose is at the end of the function and we definitely return no matter
> if it is NULL or not.

Okay, cache_lookup_{name, path}() can indeed return NULL, so the same
transformation won't work. Sorry for the noise.

^ permalink raw reply	[relevance 2%]

* Re: What's cooking in git.git (Aug 2015, #03; Mon, 17)
  @ 2015-08-17 23:28  4% ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-17 23:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org

On Mon, Aug 17, 2015 at 3:34 PM, Junio C Hamano <gitster@pobox.com> wrote:
> * hv/submodule-config (2015-06-15) 4 commits
>  - do not die on error of parsing fetchrecursesubmodules option
>  - use new config API for worktree configurations of submodules
>  - extract functions for submodule config set and lookup
>  - implement submodule config API for lookup of .gitmodules values
>
>  The gitmodules API accessed from the C code learned to cache stuff
>  lazily.

Will reroll today as part of a larger series.

> * mk/submodule-gitdir-path (2015-08-05) 2 commits
>  - path: implement common_dir handling in git_path_submodule()
>  - submodule refactor: use git_path_submodule() in add_submodule_odb()
>
>  The submodule code has been taught to work better with separate
>  work trees created via "git worktree add".
>
>  Waiting for a review.
>  ($gmane/275340).

I'll look into it.

>
> * sb/remove-get-pathspec (2015-08-03) 1 commit
>  - builtin/mv: remove get_pathspec()
>
>  Expecting a reroll.
>  ($gmane/275224)

IIRC the discussion turned out to expect a
full conversion of internal_copy_pathspec in builtin/mv
and not just moving all the cruft there, such that we can
make the deprecated function non public and update the
documentation.

So I am not going to spend more time on that series,
anyone is free to pick it up. So I guess dropping it for
now is ok.

>
>
> * sb/submodule-helper (2015-08-07) 1 commit
>  - submodule: implement `module_list` as a builtin helper
>
>  The beginning of "git submodule" rewritten in C.

This combined will be combined with hv/submodule-config

>
>
> * tb/complete-rebase-i-edit-todo (2015-08-05) 1 commit
>   (merged to 'next' on 2015-08-12 at 9606c21)
>  + completion: offer '--edit-todo' during interactive rebase
>
>  The command-line completion script (in contrib/) has been updated.
>
>  Will merge to 'master'.
>
>
> * dt/untracked-subdir (2015-08-07) 2 commits
>  - DONTMERGE: wait for Duy to Ack or comment
>  - untracked-cache: fix subdirectory handling
>
>  Waiting for a review cycle to conclude.
>  ($gmane/276019).
>
>
> * jk/test-with-x (2015-08-07) 2 commits
>   (merged to 'next' on 2015-08-12 at 06576a1)
>  + test-lib: disable trace when test is not verbose
>  + test-lib: turn off "-x" tracing during chain-lint check
>
>  Running tests with the "-x" option to make them verbose had some
>  unpleasant interactions with other features of the test suite.
>
>  Will merge to 'master'.
>
>
> * ad/cygwin-wants-rename (2015-08-07) 1 commit
>  - config.mak.uname: Cygwin needs OBJECT_CREATION_USES_RENAMES
>
>  Will hold.
>  ($gmane/275680).
>
>
> * ee/clean-remove-dirs (2015-08-11) 1 commit
>   (merged to 'next' on 2015-08-12 at fc41b09)
>  + t7300-clean: require POSIXPERM for chmod 0 test
>
>  Test updates for Windows.
>
>  Will merge to 'master'.
>
>
> * jc/finalize-temp-file (2015-08-10) 1 commit
>   (merged to 'next' on 2015-08-12 at 6fe62fe)
>  + sha1_file.c: rename move_temp_to_file() to finalize_object_file()
>
>  Long overdue micro clean-up.
>
>  Will merge to 'master'.
>
>
> * jk/git-path (2015-08-10) 16 commits
>   (merged to 'next' on 2015-08-12 at 7ebe864)
>  + memoize common git-path "constant" files
>  + get_repo_path: refactor path-allocation
>  + find_hook: keep our own static buffer
>  + refs.c: remove_empty_directories can take a strbuf
>  + refs.c: avoid git_path assignment in lock_ref_sha1_basic
>  + refs.c: avoid repeated git_path calls in rename_tmp_log
>  + refs.c: simplify strbufs in reflog setup and writing
>  + path.c: drop git_path_submodule

Oops, I just wanted to add a caller to git_path_submodule. I'll also look into
this series to see the alternatives. :)

>  + refs.c: remove extra git_path calls from read_loose_refs
>  + remote.c: drop extraneous local variable from migrate_file
>  + prefer mkpathdup to mkpath in assignments
>  + prefer git_pathdup to git_path in some possibly-dangerous cases
>  + add_to_alternates_file: don't add duplicate entries
>  + t5700: modernize style
>  + cache.h: complete set of git_path_submodule helpers
>  + cache.h: clarify documentation for git_path, et al
>
>  git_path() and mkpath() are handy helper functions but it is easy
>  to misuse, as the callers need to be careful to keep the number of
>  active results below 4.  Their uses have been reduced.
>
>  Will merge to 'master'.
>

^ permalink raw reply	[relevance 4%]

* Re: [PATCH v7 2/2] path: implement common_dir handling in git_path_submodule()
  @ 2015-08-17 23:56  2%     ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-17 23:56 UTC (permalink / raw)
  To: Max Kirillov
  Cc: Jens Lehmann, Duy Nguyen, Junio C Hamano, git@vger.kernel.org

On Tue, Aug 4, 2015 at 3:05 PM, Max Kirillov <max@max630.net> wrote:
> When submodule is a linked worktree, "git diff --submodule" and other
> calls which directly access the submodule's object database do not correctly
> calculate its path. Fix it by changing the git_path_submodule() behavior,
> to use either common or per-worktree directory.
>
> Do it similarly as for parent repository, but ignore the GIT_COMMON_DIR
> environment variable, because it would mean common directory for the parent
> repository and does not make sense for submodule.
>
> Also add test for functionality which uses this call.
>
> Signed-off-by: Max Kirillov <max@max630.net>
> ---
>  cache.h                          |  1 +
>  path.c                           | 24 ++++++++++++++++++++----
>  setup.c                          | 17 ++++++++++++-----
>  t/t7410-submodule-checkout-to.sh | 10 ++++++++++
>  4 files changed, 43 insertions(+), 9 deletions(-)
>
> diff --git a/cache.h b/cache.h
> index 4f55466..b87ec75 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -442,6 +442,7 @@ extern char *get_object_directory(void);
>  extern char *get_index_file(void);
>  extern char *get_graft_file(void);
>  extern int set_git_dir(const char *path);
> +extern int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
>  extern int get_common_dir(struct strbuf *sb, const char *gitdir);
>  extern const char *get_git_namespace(void);
>  extern const char *strip_namespace(const char *namespaced_ref);
> diff --git a/path.c b/path.c
> index 10f4cbf..b0cf444 100644
> --- a/path.c
> +++ b/path.c
> @@ -98,7 +98,7 @@ static const char *common_list[] = {
>         NULL
>  };
>
> -static void update_common_dir(struct strbuf *buf, int git_dir_len)
> +static void update_common_dir(struct strbuf *buf, int git_dir_len, const char *common_dir)
>  {
>         char *base = buf->buf + git_dir_len;
>         const char **p;
> @@ -115,12 +115,17 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len)
>                         path++;
>                         is_dir = 1;
>                 }
> +
> +               if (!common_dir) {
> +                       common_dir = get_git_common_dir();
> +               }

Usually we omit the braces for blocks with just one command.

> +
>                 if (is_dir && dir_prefix(base, path)) {
> -                       replace_dir(buf, git_dir_len, get_git_common_dir());
> +                       replace_dir(buf, git_dir_len, common_dir);
>                         return;
>                 }
>                 if (!is_dir && !strcmp(base, path)) {
> -                       replace_dir(buf, git_dir_len, get_git_common_dir());
> +                       replace_dir(buf, git_dir_len, common_dir);
>                         return;
>                 }
>         }
> @@ -160,7 +165,7 @@ static void adjust_git_path(struct strbuf *buf, int git_dir_len)
>         else if (git_db_env && dir_prefix(base, "objects"))
>                 replace_dir(buf, git_dir_len + 7, get_object_directory());
>         else if (git_common_dir_env)
> -               update_common_dir(buf, git_dir_len);
> +               update_common_dir(buf, git_dir_len, NULL);
>  }
>
>  static void do_git_path(struct strbuf *buf, const char *fmt, va_list args)
> @@ -228,6 +233,8 @@ const char *git_path_submodule(const char *path, const char *fmt, ...)
>  {
>         struct strbuf *buf = get_pathname();
>         const char *git_dir;
> +       struct strbuf git_submodule_common_dir = STRBUF_INIT;
> +       struct strbuf git_submodule_dir = STRBUF_INIT;
>         va_list args;
>
>         strbuf_addstr(buf, path);
> @@ -241,11 +248,20 @@ const char *git_path_submodule(const char *path, const char *fmt, ...)
>                 strbuf_addstr(buf, git_dir);
>         }
>         strbuf_addch(buf, '/');
> +       strbuf_addstr(&git_submodule_dir, buf->buf);
>
>         va_start(args, fmt);
>         strbuf_vaddf(buf, fmt, args);
>         va_end(args);
> +
> +       if (get_common_dir_noenv(&git_submodule_common_dir, git_submodule_dir.buf)) {
> +               update_common_dir(buf, git_submodule_dir.len, git_submodule_common_dir.buf);
> +       }
> +
>         strbuf_cleanup_path(buf);
> +
> +       strbuf_release(&git_submodule_dir);
> +       strbuf_release(&git_submodule_common_dir);
>         return buf->buf;
>  }
>
> diff --git a/setup.c b/setup.c
> index 82c0cc2..39ea06b 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -229,14 +229,21 @@ void verify_non_filename(const char *prefix, const char *arg)
>
>  int get_common_dir(struct strbuf *sb, const char *gitdir)
>  {
> +       const char *git_env_common_dir = getenv(GIT_COMMON_DIR_ENVIRONMENT);
> +       if (git_env_common_dir) {
> +               strbuf_addstr(sb, git_env_common_dir);
> +               return 1;
> +       } else {
> +               return get_common_dir_noenv(sb, gitdir);
> +       }
> +}
> +
> +int get_common_dir_noenv(struct strbuf *sb, const char *gitdir)
> +{
>         struct strbuf data = STRBUF_INIT;
>         struct strbuf path = STRBUF_INIT;
> -       const char *git_common_dir = getenv(GIT_COMMON_DIR_ENVIRONMENT);
>         int ret = 0;
> -       if (git_common_dir) {
> -               strbuf_addstr(sb, git_common_dir);
> -               return 1;
> -       }
> +
>         strbuf_addf(&path, "%s/commondir", gitdir);
>         if (file_exists(path.buf)) {
>                 if (strbuf_read_file(&data, path.buf, 0) <= 0)
> diff --git a/t/t7410-submodule-checkout-to.sh b/t/t7410-submodule-checkout-to.sh
> index 3f609e8..1acef32 100755
> --- a/t/t7410-submodule-checkout-to.sh
> +++ b/t/t7410-submodule-checkout-to.sh
> @@ -47,4 +47,14 @@ test_expect_success 'checkout main and initialize independed clones' \
>  test_expect_success 'can see submodule diffs after independed cloning' \
>      '(cd fully_cloned_submodule/main && git diff --submodule master"^!" | grep "file1 updated")'
>
> +test_expect_success 'checkout sub manually' \
> +    'mkdir linked_submodule &&
> +    (cd clone/main &&
> +       git worktree add "$base_path/linked_submodule/main" "$rev1_hash_main") &&
> +    (cd clone/main/sub &&
> +       git worktree add "$base_path/linked_submodule/main/sub" "$rev1_hash_sub")'
> +
> +test_expect_success 'can see submodule diffs after manual checkout of linked submodule' \
> +    '(cd linked_submodule/main && git diff --submodule master"^!" | grep "file1 updated")'
> +
>  test_done
> --
> 2.3.4.2801.g3d0809b

Looks good to me otherwise.

>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 2%]

* Re: [PATCH v7 1/2] submodule refactor: use git_path_submodule() in add_submodule_odb()
  @ 2015-08-18  0:07  7%     ` Stefan Beller
  0 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:07 UTC (permalink / raw)
  To: Max Kirillov
  Cc: Jens Lehmann, Duy Nguyen, Junio C Hamano, git@vger.kernel.org

On Tue, Aug 4, 2015 at 3:05 PM, Max Kirillov <max@max630.net> wrote:
> Functions which directly operate submodule's object database do not handle the
> case when the submodule is linked worktree (which are introduced in
> c7b3a3d2fe). Instead of fixing the path calculation use already existing
> git_path_submodule() function without changing overall behavior. Then it will
> be possible to modify only that function whenever we need to change real
> location of submodule's repository content.
>
> Signed-off-by: Max Kirillov <max@max630.net>
> ---
>  submodule.c | 28 ++++++++++------------------
>  1 file changed, 10 insertions(+), 18 deletions(-)
>
> diff --git a/submodule.c b/submodule.c
> index 15e90d1..70d18ec 100644
> --- a/submodule.c
> +++ b/submodule.c
> @@ -122,43 +122,35 @@ void stage_updated_gitmodules(void)
>
>  static int add_submodule_odb(const char *path)
>  {
> -       struct strbuf objects_directory = STRBUF_INIT;
>         struct alternate_object_database *alt_odb;
> +       const char *objects_directory;
>         int ret = 0;
> -       const char *git_dir;
>
> -       strbuf_addf(&objects_directory, "%s/.git", path);
> -       git_dir = read_gitfile(objects_directory.buf);
> -       if (git_dir) {
> -               strbuf_reset(&objects_directory);
> -               strbuf_addstr(&objects_directory, git_dir);
> -       }
> -       strbuf_addstr(&objects_directory, "/objects/");
> -       if (!is_directory(objects_directory.buf)) {
> +       objects_directory = git_path_submodule(path, "objects/");

git_path_submodule is going away with  jk/git-path (2015-08-10)
So you may want to use git_pathdup_submodule and free the
result of that function before returning.

> +       if (!is_directory(objects_directory)) {
>                 ret = -1;
>                 goto done;
>         }
> +
>         /* avoid adding it twice */
>         for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
> -               if (alt_odb->name - alt_odb->base == objects_directory.len &&
> -                               !strncmp(alt_odb->base, objects_directory.buf,
> -                                       objects_directory.len))
> +               if (alt_odb->name - alt_odb->base == strlen(objects_directory) &&
> +                               !strcmp(alt_odb->base, objects_directory))
>                         goto done;
>
> -       alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb));
> +       alt_odb = xmalloc(strlen(objects_directory) + 42 + sizeof(*alt_odb));
>         alt_odb->next = alt_odb_list;
> -       strcpy(alt_odb->base, objects_directory.buf);
> -       alt_odb->name = alt_odb->base + objects_directory.len;
> +       strcpy(alt_odb->base, objects_directory);
> +       alt_odb->name = alt_odb->base + strlen(objects_directory);
>         alt_odb->name[2] = '/';
>         alt_odb->name[40] = '\0';
>         alt_odb->name[41] = '\0';
>         alt_odb_list = alt_odb;
>
>         /* add possible alternates from the submodule */
> -       read_info_alternates(objects_directory.buf, 0);
> +       read_info_alternates(objects_directory, 0);
>         prepare_alt_odb();
>  done:
> -       strbuf_release(&objects_directory);
>         return ret;
>  }
>

This looks good, though I am diving into the submodule code base
myself just now,
so it's not a strong review. :)

> --
> 2.3.4.2801.g3d0809b
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 7%]

* [PATCH 0/7] Submodule improvements
@ 2015-08-18  0:21  9% Stefan Beller
  2015-08-18  0:21 14% ` [PATCH 1/7] submodule: implement a config API for lookup of .gitmodules values Stefan Beller
                   ` (7 more replies)
  0 siblings, 8 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:21 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

This series is a reroll consisting of hv/submodule-config and 
sb/submodule-helper and it applies on top of origin/jk/git-path.

Our long term goal is to make submodule handling more scalable
by parallelizing the submodule code. To write good parallelizable
code I'd first want to port it to C, as there are no good portable
solutions for shell scripts to run in parallel. This series is a
first step on porting git-submodule.sh to C.

I did not alter the patches of Heiko, except for squashing
$gmane/275799 (2 cleanup patches I proposed 5 days ago).

The module_{list, name, clone} functions are a direct translation
of the shell counter parts. I took way longer than expected for
module_clone, as I was fighting with absolute and relative paths
for too long. (Whenever shell is translated to C,
I estimate two times the number of lines of code which fits
quite reasonably.)

Thanks,
Stefan

Heiko Voigt (4):
  submodule: implement a config API for lookup of .gitmodules values
  submodule: extract functions for config set and lookup
  submodule: use new config API for worktree configurations
  submodule: Allow errornous values for the fetchrecursesubmodules
    option

Stefan Beller (3):
  submodule: implement `module_list` as a builtin helper
  submodule: implement `module_name` as a builtin helper
  submodule: implement `module_clone` as a builtin helper

 .gitignore                                       |   2 +
 Documentation/technical/api-submodule-config.txt |  62 +++
 Makefile                                         |   3 +
 builtin.h                                        |   1 +
 builtin/checkout.c                               |   1 +
 builtin/fetch.c                                  |   1 +
 builtin/submodule--helper.c                      | 299 ++++++++++++++
 diff.c                                           |   1 +
 git-submodule.sh                                 | 164 +-------
 git.c                                            |   1 +
 submodule-config.c                               | 482 +++++++++++++++++++++++
 submodule-config.h                               |  29 ++
 submodule.c                                      | 122 ++----
 submodule.h                                      |   4 +-
 t/t7411-submodule-config.sh                      | 153 +++++++
 test-submodule-config.c                          |  76 ++++
 16 files changed, 1154 insertions(+), 247 deletions(-)
 create mode 100644 Documentation/technical/api-submodule-config.txt
 create mode 100644 builtin/submodule--helper.c
 create mode 100644 submodule-config.c
 create mode 100644 submodule-config.h
 create mode 100755 t/t7411-submodule-config.sh
 create mode 100644 test-submodule-config.c

-- 
2.5.0.330.g130be8e.dirty

^ permalink raw reply	[relevance 9%]

* [PATCH 2/7] submodule: extract functions for config set and lookup
  2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
  2015-08-18  0:21 14% ` [PATCH 1/7] submodule: implement a config API for lookup of .gitmodules values Stefan Beller
@ 2015-08-18  0:21 11% ` Stefan Beller
  2015-08-18  0:21 23% ` [PATCH 3/7] submodule: use new config API for worktree configurations Stefan Beller
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:21 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

From: Heiko Voigt <hvoigt@hvoigt.net>

This is one step towards using the new configuration API. We just
extract these functions to make replacing the actual code easier.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 submodule.c | 142 +++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 97 insertions(+), 45 deletions(-)

diff --git a/submodule.c b/submodule.c
index 17b54e4..307fa43 100644
--- a/submodule.c
+++ b/submodule.c
@@ -41,6 +41,76 @@ static int gitmodules_is_unmerged;
  */
 static int gitmodules_is_modified;
 
+static const char *get_name_for_path(const char *path)
+{
+	struct string_list_item *path_option;
+	if (path == NULL) {
+		if (config_name_for_path.nr > 0)
+			return config_name_for_path.items[0].util;
+		else
+			return NULL;
+	}
+	path_option = unsorted_string_list_lookup(&config_name_for_path, path);
+	if (!path_option)
+		return NULL;
+	return path_option->util;
+}
+
+static void set_name_for_path(const char *path, const char *name, int namelen)
+{
+	struct string_list_item *config;
+	config = unsorted_string_list_lookup(&config_name_for_path, path);
+	if (config)
+		free(config->util);
+	else
+		config = string_list_append(&config_name_for_path, xstrdup(path));
+	config->util = xmemdupz(name, namelen);
+}
+
+static const char *get_ignore_for_name(const char *name)
+{
+	struct string_list_item *ignore_option;
+	ignore_option = unsorted_string_list_lookup(&config_ignore_for_name, name);
+	if (!ignore_option)
+		return NULL;
+
+	return ignore_option->util;
+}
+
+static void set_ignore_for_name(const char *name, int namelen, const char *ignore)
+{
+	struct string_list_item *config;
+	char *name_cstr = xmemdupz(name, namelen);
+	config = unsorted_string_list_lookup(&config_ignore_for_name, name_cstr);
+	if (config) {
+		free(config->util);
+		free(name_cstr);
+	} else
+		config = string_list_append(&config_ignore_for_name, name_cstr);
+	config->util = xstrdup(ignore);
+}
+
+static int get_fetch_recurse_for_name(const char *name)
+{
+	struct string_list_item *fetch_recurse;
+	fetch_recurse = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name);
+	if (!fetch_recurse)
+		return RECURSE_SUBMODULES_NONE;
+
+	return (intptr_t) fetch_recurse->util;
+}
+
+static void set_fetch_recurse_for_name(const char *name, int namelen, int fetch_recurse)
+{
+	struct string_list_item *config;
+	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, name_cstr);
+	else
+		free(name_cstr);
+	config->util = (void *)(intptr_t) fetch_recurse;
+}
 
 int is_staging_gitmodules_ok(void)
 {
@@ -55,7 +125,7 @@ int is_staging_gitmodules_ok(void)
 int update_path_in_gitmodules(const char *oldpath, const char *newpath)
 {
 	struct strbuf entry = STRBUF_INIT;
-	struct string_list_item *path_option;
+	const char *path;
 
 	if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */
 		return -1;
@@ -63,13 +133,13 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
 	if (gitmodules_is_unmerged)
 		die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
 
-	path_option = unsorted_string_list_lookup(&config_name_for_path, oldpath);
-	if (!path_option) {
+	path = get_name_for_path(oldpath);
+	if (!path) {
 		warning(_("Could not find section in .gitmodules where path=%s"), oldpath);
 		return -1;
 	}
 	strbuf_addstr(&entry, "submodule.");
-	strbuf_addstr(&entry, path_option->util);
+	strbuf_addstr(&entry, path);
 	strbuf_addstr(&entry, ".path");
 	if (git_config_set_in_file(".gitmodules", entry.buf, newpath) < 0) {
 		/* Maybe the user already did that, don't error out here */
@@ -89,7 +159,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
 int remove_path_from_gitmodules(const char *path)
 {
 	struct strbuf sect = STRBUF_INIT;
-	struct string_list_item *path_option;
+	const char *path_option;
 
 	if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */
 		return -1;
@@ -97,13 +167,13 @@ int remove_path_from_gitmodules(const char *path)
 	if (gitmodules_is_unmerged)
 		die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
 
-	path_option = unsorted_string_list_lookup(&config_name_for_path, path);
+	path_option = get_name_for_path(path);
 	if (!path_option) {
 		warning(_("Could not find section in .gitmodules where path=%s"), path);
 		return -1;
 	}
 	strbuf_addstr(&sect, "submodule.");
-	strbuf_addstr(&sect, path_option->util);
+	strbuf_addstr(&sect, path_option);
 	if (git_config_rename_section_in_file(".gitmodules", sect.buf, NULL) < 0) {
 		/* Maybe the user already did that, don't error out here */
 		warning(_("Could not remove .gitmodules entry for %s"), path);
@@ -165,12 +235,11 @@ done:
 void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
 					     const char *path)
 {
-	struct string_list_item *path_option, *ignore_option;
-	path_option = unsorted_string_list_lookup(&config_name_for_path, path);
-	if (path_option) {
-		ignore_option = unsorted_string_list_lookup(&config_ignore_for_name, path_option->util);
-		if (ignore_option)
-			handle_ignore_submodules_arg(diffopt, ignore_option->util);
+	const char *name = get_name_for_path(path);
+	if (name) {
+		const char *ignore = get_ignore_for_name(name);
+		if (ignore)
+			handle_ignore_submodules_arg(diffopt, ignore);
 		else if (gitmodules_is_unmerged)
 			DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
 	}
@@ -221,7 +290,6 @@ void gitmodules_config(void)
 
 int parse_submodule_config_option(const char *var, const char *value)
 {
-	struct string_list_item *config;
 	const char *name, *key;
 	int namelen;
 
@@ -232,22 +300,14 @@ int parse_submodule_config_option(const char *var, const char *value)
 		if (!value)
 			return config_error_nonbool(var);
 
-		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 = xmemdupz(name, namelen);
+		set_name_for_path(value, name, namelen);
+
 	} else if (!strcmp(key, "fetchrecursesubmodules")) {
-		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, name_cstr);
-		else
-			free(name_cstr);
-		config->util = (void *)(intptr_t)parse_fetch_recurse_submodules_arg(var, value);
+		int fetch_recurse = parse_fetch_recurse_submodules_arg(var, value);
+
+		set_fetch_recurse_for_name(name, namelen, fetch_recurse);
+
 	} else if (!strcmp(key, "ignore")) {
-		char *name_cstr;
 
 		if (!value)
 			return config_error_nonbool(var);
@@ -258,14 +318,7 @@ int parse_submodule_config_option(const char *var, const char *value)
 			return 0;
 		}
 
-		name_cstr = xmemdupz(name, namelen);
-		config = unsorted_string_list_lookup(&config_ignore_for_name, name_cstr);
-		if (config) {
-			free(config->util);
-			free(name_cstr);
-		} else
-			config = string_list_append(&config_ignore_for_name, name_cstr);
-		config->util = xstrdup(value);
+		set_ignore_for_name(name, namelen, value);
 		return 0;
 	}
 	return 0;
@@ -647,7 +700,7 @@ static void calculate_changed_submodule_paths(void)
 	struct argv_array argv = ARGV_ARRAY_INIT;
 
 	/* No need to check if there are no submodules configured */
-	if (!config_name_for_path.nr)
+	if (!get_name_for_path(NULL))
 		return;
 
 	init_revisions(&rev, NULL);
@@ -694,7 +747,7 @@ int fetch_populated_submodules(const struct argv_array *options,
 	int i, result = 0;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	struct argv_array argv = ARGV_ARRAY_INIT;
-	struct string_list_item *name_for_path;
+	const char *name_for_path;
 	const char *work_tree = get_git_work_tree();
 	if (!work_tree)
 		goto out;
@@ -725,18 +778,17 @@ int fetch_populated_submodules(const struct argv_array *options,
 			continue;
 
 		name = ce->name;
-		name_for_path = unsorted_string_list_lookup(&config_name_for_path, ce->name);
+		name_for_path = get_name_for_path(ce->name);
 		if (name_for_path)
-			name = name_for_path->util;
+			name = name_for_path;
 
 		default_argv = "yes";
 		if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
-			struct string_list_item *fetch_recurse_submodules_option;
-			fetch_recurse_submodules_option = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name);
-			if (fetch_recurse_submodules_option) {
-				if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_OFF)
+			int fetch_recurse_option = get_fetch_recurse_for_name(name);
+			if (fetch_recurse_option != RECURSE_SUBMODULES_NONE) {
+				if (fetch_recurse_option == RECURSE_SUBMODULES_OFF)
 					continue;
-				if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_ON_DEMAND) {
+				if (fetch_recurse_option == RECURSE_SUBMODULES_ON_DEMAND) {
 					if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
 						continue;
 					default_argv = "on-demand";
-- 
2.5.0.330.g130be8e.dirty

^ permalink raw reply related	[relevance 11%]

* [PATCH 1/7] submodule: implement a config API for lookup of .gitmodules values
  2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
@ 2015-08-18  0:21 14% ` Stefan Beller
  2015-08-18  0:21 11% ` [PATCH 2/7] submodule: extract functions for config set and lookup Stefan Beller
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:21 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

From: Heiko Voigt <hvoigt@hvoigt.net>

In a superproject some commands need to interact with submodules. They
need to query values from the .gitmodules file either from the worktree
of from certain revisions. At the moment this is quite hard since a
caller would need to read the .gitmodules file from the history and then
parse the values. We want to provide an API for this so we have one
place to get values from .gitmodules from any revision (including the
worktree).

The API is realized as a cache which allows us to lazily read
.gitmodules configurations by commit into a runtime cache which can then
be used to easily lookup values from it. Currently only the values for
path or name are stored but it can be extended for any value needed.

It is expected that .gitmodules files do not change often between
commits. Thats why we lookup the .gitmodules sha1 from a commit and then
either lookup an already parsed configuration or parse and cache an
unknown one for each sha1. The cache is lazily build on demand for each
requested commit.

This cache can be used for all purposes which need knowledge about
submodule configurations. Example use cases are:

 * Recursive submodule checkout needs to lookup a submodule name from
   its path when a submodule first appears. This needs be done before
   this configuration exists in the worktree.

 * The implementation of submodule support for 'git archive' needs to
   lookup the submodule name to generate the archive when given a
   revision that is not checked out.

 * 'git fetch' when given the --recurse-submodules=on-demand option (or
   configuration) needs to lookup submodule names by path from the
   database rather than reading from the worktree. For new submodule it
   needs to lookup the name from its path to allow cloning new
   submodules into the .git folder so they can be checked out without
   any network interaction when the user does a checkout of that
   revision.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 .gitignore                                       |   1 +
 Documentation/technical/api-submodule-config.txt |  45 +++
 Makefile                                         |   2 +
 submodule-config.c                               | 443 +++++++++++++++++++++++
 submodule-config.h                               |  27 ++
 submodule.c                                      |   1 +
 submodule.h                                      |   1 +
 t/t7411-submodule-config.sh                      |  85 +++++
 test-submodule-config.c                          |  66 ++++
 9 files changed, 671 insertions(+)
 create mode 100644 Documentation/technical/api-submodule-config.txt
 create mode 100644 submodule-config.c
 create mode 100644 submodule-config.h
 create mode 100755 t/t7411-submodule-config.sh
 create mode 100644 test-submodule-config.c

diff --git a/.gitignore b/.gitignore
index a685ec1..4fd81ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -205,6 +205,7 @@
 /test-sha1-array
 /test-sigchain
 /test-string-list
+/test-submodule-config
 /test-subprocess
 /test-svn-fe
 /test-urlmatch-normalization
diff --git a/Documentation/technical/api-submodule-config.txt b/Documentation/technical/api-submodule-config.txt
new file mode 100644
index 0000000..1fbde41
--- /dev/null
+++ b/Documentation/technical/api-submodule-config.txt
@@ -0,0 +1,45 @@
+submodule config cache API
+==========================
+
+The submodule config cache API allows to read submodule
+configurations/information from specified revisions. Internally
+information is lazily read into a cache that is used to avoid
+unnecessary parsing of the same .gitmodule files. Lookups can be done by
+submodule path or name.
+
+Usage
+-----
+
+The caller can look up information about submodules by using the
+`submodule_from_path()` or `submodule_from_name()` functions. They return
+a `struct submodule` which contains the values. The API automatically
+initializes and allocates the needed infrastructure on-demand.
+
+If the internal cache might grow too big or when the caller is done with
+the API, all internally cached values can be freed with submodule_free().
+
+Data Structures
+---------------
+
+`struct submodule`::
+
+	This structure is used to return the information about one
+	submodule for a certain revision. It is returned by the lookup
+	functions.
+
+Functions
+---------
+
+`void submodule_free()`::
+
+	Use these to free the internally cached values.
+
+`const struct submodule *submodule_from_path(const unsigned char *commit_sha1, const char *path)`::
+
+	Lookup values for one submodule by its commit_sha1 and path.
+
+`const struct submodule *submodule_from_name(const unsigned char *commit_sha1, const char *name)`::
+
+	The same as above but lookup by name.
+
+For an example usage see test-submodule-config.c.
diff --git a/Makefile b/Makefile
index 7efedbe..24b636d 100644
--- a/Makefile
+++ b/Makefile
@@ -594,6 +594,7 @@ TEST_PROGRAMS_NEED_X += test-sha1
 TEST_PROGRAMS_NEED_X += test-sha1-array
 TEST_PROGRAMS_NEED_X += test-sigchain
 TEST_PROGRAMS_NEED_X += test-string-list
+TEST_PROGRAMS_NEED_X += test-submodule-config
 TEST_PROGRAMS_NEED_X += test-subprocess
 TEST_PROGRAMS_NEED_X += test-svn-fe
 TEST_PROGRAMS_NEED_X += test-urlmatch-normalization
@@ -785,6 +786,7 @@ LIB_OBJS += strbuf.o
 LIB_OBJS += streaming.o
 LIB_OBJS += string-list.o
 LIB_OBJS += submodule.o
+LIB_OBJS += submodule-config.o
 LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += trace.o
diff --git a/submodule-config.c b/submodule-config.c
new file mode 100644
index 0000000..ea82edb
--- /dev/null
+++ b/submodule-config.c
@@ -0,0 +1,443 @@
+#include "cache.h"
+#include "submodule-config.h"
+#include "submodule.h"
+#include "strbuf.h"
+
+/*
+ * submodule cache lookup structure
+ * There is one shared set of 'struct submodule' entries which can be
+ * looked up by their sha1 blob id of the .gitmodule file and either
+ * using path or name as key.
+ * for_path stores submodule entries with path as key
+ * for_name stores submodule entries with name as key
+ */
+struct submodule_cache {
+	struct hashmap for_path;
+	struct hashmap for_name;
+};
+
+/*
+ * thin wrapper struct needed to insert 'struct submodule' entries to
+ * the hashmap
+ */
+struct submodule_entry {
+	struct hashmap_entry ent;
+	struct submodule *config;
+};
+
+enum lookup_type {
+	lookup_name,
+	lookup_path
+};
+
+static struct submodule_cache cache;
+static int is_cache_init;
+
+static int config_path_cmp(const struct submodule_entry *a,
+			   const struct submodule_entry *b,
+			   const void *unused)
+{
+	return strcmp(a->config->path, b->config->path) ||
+	       hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
+}
+
+static int config_name_cmp(const struct submodule_entry *a,
+			   const struct submodule_entry *b,
+			   const void *unused)
+{
+	return strcmp(a->config->name, b->config->name) ||
+	       hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
+}
+
+static void cache_init(struct submodule_cache *cache)
+{
+	hashmap_init(&cache->for_path, (hashmap_cmp_fn) config_path_cmp, 0);
+	hashmap_init(&cache->for_name, (hashmap_cmp_fn) config_name_cmp, 0);
+}
+
+static void free_one_config(struct submodule_entry *entry)
+{
+	free((void *) entry->config->path);
+	free((void *) entry->config->name);
+	free(entry->config);
+}
+
+static void cache_free(struct submodule_cache *cache)
+{
+	struct hashmap_iter iter;
+	struct submodule_entry *entry;
+
+	/*
+	 * We iterate over the name hash here to be symmetric with the
+	 * allocation of struct submodule entries. Each is allocated by
+	 * their .gitmodule blob sha1 and submodule name.
+	 */
+	hashmap_iter_init(&cache->for_name, &iter);
+	while ((entry = hashmap_iter_next(&iter)))
+		free_one_config(entry);
+
+	hashmap_free(&cache->for_path, 1);
+	hashmap_free(&cache->for_name, 1);
+}
+
+static unsigned int hash_sha1_string(const unsigned char *sha1,
+				     const char *string)
+{
+	return memhash(sha1, 20) + strhash(string);
+}
+
+static void cache_put_path(struct submodule_cache *cache,
+			   struct submodule *submodule)
+{
+	unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
+					     submodule->path);
+	struct submodule_entry *e = xmalloc(sizeof(*e));
+	hashmap_entry_init(e, hash);
+	e->config = submodule;
+	hashmap_put(&cache->for_path, e);
+}
+
+static void cache_remove_path(struct submodule_cache *cache,
+			      struct submodule *submodule)
+{
+	unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
+					     submodule->path);
+	struct submodule_entry e;
+	struct submodule_entry *removed;
+	hashmap_entry_init(&e, hash);
+	e.config = submodule;
+	removed = hashmap_remove(&cache->for_path, &e, NULL);
+	free(removed);
+}
+
+static void cache_add(struct submodule_cache *cache,
+		      struct submodule *submodule)
+{
+	unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
+					     submodule->name);
+	struct submodule_entry *e = xmalloc(sizeof(*e));
+	hashmap_entry_init(e, hash);
+	e->config = submodule;
+	hashmap_add(&cache->for_name, e);
+}
+
+static const struct submodule *cache_lookup_path(struct submodule_cache *cache,
+		const unsigned char *gitmodules_sha1, const char *path)
+{
+	struct submodule_entry *entry;
+	unsigned int hash = hash_sha1_string(gitmodules_sha1, path);
+	struct submodule_entry key;
+	struct submodule key_config;
+
+	hashcpy(key_config.gitmodules_sha1, gitmodules_sha1);
+	key_config.path = path;
+
+	hashmap_entry_init(&key, hash);
+	key.config = &key_config;
+
+	entry = hashmap_get(&cache->for_path, &key, NULL);
+	if (entry)
+		return entry->config;
+	return NULL;
+}
+
+static struct submodule *cache_lookup_name(struct submodule_cache *cache,
+		const unsigned char *gitmodules_sha1, const char *name)
+{
+	struct submodule_entry *entry;
+	unsigned int hash = hash_sha1_string(gitmodules_sha1, name);
+	struct submodule_entry key;
+	struct submodule key_config;
+
+	hashcpy(key_config.gitmodules_sha1, gitmodules_sha1);
+	key_config.name = name;
+
+	hashmap_entry_init(&key, hash);
+	key.config = &key_config;
+
+	entry = hashmap_get(&cache->for_name, &key, NULL);
+	if (entry)
+		return entry->config;
+	return NULL;
+}
+
+static int name_and_item_from_var(const char *var, struct strbuf *name,
+				  struct strbuf *item)
+{
+	const char *subsection, *key;
+	int subsection_len, parse;
+	parse = parse_config_key(var, "submodule", &subsection,
+			&subsection_len, &key);
+	if (parse < 0 || !subsection)
+		return 0;
+
+	strbuf_add(name, subsection, subsection_len);
+	strbuf_addstr(item, key);
+
+	return 1;
+}
+
+static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,
+		const unsigned char *gitmodules_sha1, const char *name)
+{
+	struct submodule *submodule;
+	struct strbuf name_buf = STRBUF_INIT;
+
+	submodule = cache_lookup_name(cache, gitmodules_sha1, name);
+	if (submodule)
+		return submodule;
+
+	submodule = xmalloc(sizeof(*submodule));
+
+	strbuf_addstr(&name_buf, name);
+	submodule->name = strbuf_detach(&name_buf, NULL);
+
+	submodule->path = NULL;
+	submodule->url = NULL;
+	submodule->fetch_recurse = RECURSE_SUBMODULES_NONE;
+	submodule->ignore = NULL;
+
+	hashcpy(submodule->gitmodules_sha1, gitmodules_sha1);
+
+	cache_add(cache, submodule);
+
+	return submodule;
+}
+
+static void warn_multiple_config(const unsigned char *commit_sha1,
+				 const char *name, const char *option)
+{
+	const char *commit_string = "WORKTREE";
+	if (commit_sha1)
+		commit_string = sha1_to_hex(commit_sha1);
+	warning("%s:.gitmodules, multiple configurations found for "
+			"'submodule.%s.%s'. Skipping second one!",
+			commit_string, name, option);
+}
+
+struct parse_config_parameter {
+	struct submodule_cache *cache;
+	const unsigned char *commit_sha1;
+	const unsigned char *gitmodules_sha1;
+	int overwrite;
+};
+
+static int parse_config(const char *var, const char *value, void *data)
+{
+	struct parse_config_parameter *me = data;
+	struct submodule *submodule;
+	struct strbuf name = STRBUF_INIT, item = STRBUF_INIT;
+	int ret = 0;
+
+	/* this also ensures that we only parse submodule entries */
+	if (!name_and_item_from_var(var, &name, &item))
+		return 0;
+
+	submodule = lookup_or_create_by_name(me->cache, me->gitmodules_sha1,
+			name.buf);
+
+	if (!strcmp(item.buf, "path")) {
+		struct strbuf path = STRBUF_INIT;
+		if (!value) {
+			ret = config_error_nonbool(var);
+			goto release_return;
+		}
+		if (!me->overwrite && submodule->path != NULL) {
+			warn_multiple_config(me->commit_sha1, submodule->name,
+					"path");
+			goto release_return;
+		}
+
+		if (submodule->path)
+			cache_remove_path(me->cache, submodule);
+		free((void *) submodule->path);
+		strbuf_addstr(&path, value);
+		submodule->path = strbuf_detach(&path, NULL);
+		cache_put_path(me->cache, submodule);
+	} else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
+		if (!me->overwrite &&
+		    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) {
+			warn_multiple_config(me->commit_sha1, submodule->name,
+					"fetchrecursesubmodules");
+			goto release_return;
+		}
+
+		submodule->fetch_recurse = parse_fetch_recurse_submodules_arg(var, value);
+	} else if (!strcmp(item.buf, "ignore")) {
+		struct strbuf ignore = STRBUF_INIT;
+		if (!me->overwrite && submodule->ignore != NULL) {
+			warn_multiple_config(me->commit_sha1, submodule->name,
+					"ignore");
+			goto release_return;
+		}
+		if (!value) {
+			ret = config_error_nonbool(var);
+			goto release_return;
+		}
+		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);
+			goto release_return;
+		}
+
+		free((void *) submodule->ignore);
+		strbuf_addstr(&ignore, value);
+		submodule->ignore = strbuf_detach(&ignore, NULL);
+	} else if (!strcmp(item.buf, "url")) {
+		struct strbuf url = STRBUF_INIT;
+		if (!value) {
+			ret = config_error_nonbool(var);
+			goto release_return;
+		}
+		if (!me->overwrite && submodule->url != NULL) {
+			warn_multiple_config(me->commit_sha1, submodule->name,
+					"url");
+			goto release_return;
+		}
+
+		free((void *) submodule->url);
+		strbuf_addstr(&url, value);
+		submodule->url = strbuf_detach(&url, NULL);
+	}
+
+release_return:
+	strbuf_release(&name);
+	strbuf_release(&item);
+
+	return ret;
+}
+
+static int gitmodule_sha1_from_commit(const unsigned char *commit_sha1,
+				      unsigned char *gitmodules_sha1)
+{
+	struct strbuf rev = STRBUF_INIT;
+	int ret = 0;
+
+	if (is_null_sha1(commit_sha1)) {
+		hashcpy(gitmodules_sha1, null_sha1);
+		return 1;
+	}
+
+	strbuf_addf(&rev, "%s:.gitmodules", sha1_to_hex(commit_sha1));
+	if (get_sha1(rev.buf, gitmodules_sha1) >= 0)
+		ret = 1;
+
+	strbuf_release(&rev);
+	return ret;
+}
+
+/* This does a lookup of a submodule configuration by name or by path
+ * (key) with on-demand reading of the appropriate .gitmodules from
+ * revisions.
+ */
+static const struct submodule *config_from(struct submodule_cache *cache,
+		const unsigned char *commit_sha1, const char *key,
+		enum lookup_type lookup_type)
+{
+	struct strbuf rev = STRBUF_INIT;
+	unsigned long config_size;
+	char *config;
+	unsigned char sha1[20];
+	enum object_type type;
+	const struct submodule *submodule = NULL;
+	struct parse_config_parameter parameter;
+
+	/*
+	 * If any parameter except the cache is a NULL pointer just
+	 * return the first submodule. Can be used to check whether
+	 * there are any submodules parsed.
+	 */
+	if (!commit_sha1 || !key) {
+		struct hashmap_iter iter;
+		struct submodule_entry *entry;
+
+		hashmap_iter_init(&cache->for_name, &iter);
+		entry = hashmap_iter_next(&iter);
+		if (!entry)
+			return NULL;
+		return entry->config;
+	}
+
+	if (!gitmodule_sha1_from_commit(commit_sha1, sha1))
+		return NULL;
+
+	switch (lookup_type) {
+	case lookup_name:
+		submodule = cache_lookup_name(cache, sha1, key);
+		break;
+	case lookup_path:
+		submodule = cache_lookup_path(cache, sha1, key);
+		break;
+	}
+	if (submodule)
+		return submodule;
+
+	config = read_sha1_file(sha1, &type, &config_size);
+	if (!config)
+		return NULL;
+
+	if (type != OBJ_BLOB) {
+		free(config);
+		return NULL;
+	}
+
+	/* fill the submodule config into the cache */
+	parameter.cache = cache;
+	parameter.commit_sha1 = commit_sha1;
+	parameter.gitmodules_sha1 = sha1;
+	parameter.overwrite = 0;
+	git_config_from_buf(parse_config, rev.buf, config, config_size,
+			&parameter);
+	free(config);
+
+	switch (lookup_type) {
+	case lookup_name:
+		return cache_lookup_name(cache, sha1, key);
+	case lookup_path:
+		return cache_lookup_path(cache, sha1, key);
+	default:
+		return NULL;
+	}
+}
+
+static const struct submodule *config_from_path(struct submodule_cache *cache,
+		const unsigned char *commit_sha1, const char *path)
+{
+	return config_from(cache, commit_sha1, path, lookup_path);
+}
+
+static const struct submodule *config_from_name(struct submodule_cache *cache,
+		const unsigned char *commit_sha1, const char *name)
+{
+	return config_from(cache, commit_sha1, name, lookup_name);
+}
+
+static void ensure_cache_init(void)
+{
+	if (is_cache_init)
+		return;
+
+	cache_init(&cache);
+	is_cache_init = 1;
+}
+
+const struct submodule *submodule_from_name(const unsigned char *commit_sha1,
+		const char *name)
+{
+	ensure_cache_init();
+	return config_from_name(&cache, commit_sha1, name);
+}
+
+const struct submodule *submodule_from_path(const unsigned char *commit_sha1,
+		const char *path)
+{
+	ensure_cache_init();
+	return config_from_path(&cache, commit_sha1, path);
+}
+
+void submodule_free(void)
+{
+	cache_free(&cache);
+	is_cache_init = 0;
+}
diff --git a/submodule-config.h b/submodule-config.h
new file mode 100644
index 0000000..cd68030
--- /dev/null
+++ b/submodule-config.h
@@ -0,0 +1,27 @@
+#ifndef SUBMODULE_CONFIG_CACHE_H
+#define SUBMODULE_CONFIG_CACHE_H
+
+#include "hashmap.h"
+#include "strbuf.h"
+
+/*
+ * Submodule entry containing the information about a certain submodule
+ * in a certain revision.
+ */
+struct submodule {
+	const char *path;
+	const char *name;
+	const char *url;
+	int fetch_recurse;
+	const char *ignore;
+	/* the sha1 blob id of the responsible .gitmodules file */
+	unsigned char gitmodules_sha1[20];
+};
+
+const struct submodule *submodule_from_name(const unsigned char *commit_sha1,
+		const char *name);
+const struct submodule *submodule_from_path(const unsigned char *commit_sha1,
+		const char *path);
+void submodule_free(void);
+
+#endif /* SUBMODULE_CONFIG_H */
diff --git a/submodule.c b/submodule.c
index 700bbf4..17b54e4 100644
--- a/submodule.c
+++ b/submodule.c
@@ -355,6 +355,7 @@ int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
 	default:
 		if (!strcmp(arg, "on-demand"))
 			return RECURSE_SUBMODULES_ON_DEMAND;
+		/* TODO: remove the die for history parsing here */
 		die("bad %s argument: %s", opt, arg);
 	}
 }
diff --git a/submodule.h b/submodule.h
index 7beec48..920fef3 100644
--- a/submodule.h
+++ b/submodule.h
@@ -5,6 +5,7 @@ struct diff_options;
 struct argv_array;
 
 enum {
+	RECURSE_SUBMODULES_NONE = -2,
 	RECURSE_SUBMODULES_ON_DEMAND = -1,
 	RECURSE_SUBMODULES_OFF = 0,
 	RECURSE_SUBMODULES_DEFAULT = 1,
diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh
new file mode 100755
index 0000000..2602bc5
--- /dev/null
+++ b/t/t7411-submodule-config.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Heiko Voigt
+#
+
+test_description='Test submodules config cache infrastructure
+
+This test verifies that parsing .gitmodules configuration directly
+from the database works.
+'
+
+TEST_NO_CREATE_REPO=1
+. ./test-lib.sh
+
+test_expect_success 'submodule config cache setup' '
+	mkdir submodule &&
+	(cd submodule &&
+		git init &&
+		echo a >a &&
+		git add . &&
+		git commit -ma
+	) &&
+	mkdir super &&
+	(cd super &&
+		git init &&
+		git submodule add ../submodule &&
+		git submodule add ../submodule a &&
+		git commit -m "add as submodule and as a" &&
+		git mv a b &&
+		git commit -m "move a to b"
+	)
+'
+
+cat >super/expect <<EOF
+Submodule name: 'a' for path 'a'
+Submodule name: 'a' for path 'b'
+Submodule name: 'submodule' for path 'submodule'
+Submodule name: 'submodule' for path 'submodule'
+EOF
+
+test_expect_success 'test parsing and lookup of submodule config by path' '
+	(cd super &&
+		test-submodule-config \
+			HEAD^ a \
+			HEAD b \
+			HEAD^ submodule \
+			HEAD submodule \
+				>actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'test parsing and lookup of submodule config by name' '
+	(cd super &&
+		test-submodule-config --name \
+			HEAD^ a \
+			HEAD a \
+			HEAD^ submodule \
+			HEAD submodule \
+				>actual &&
+		test_cmp expect actual
+	)
+'
+
+cat >super/expect_error <<EOF
+Submodule name: 'a' for path 'b'
+Submodule name: 'submodule' for path 'submodule'
+EOF
+
+test_expect_success 'error in one submodule config lets continue' '
+	(cd super &&
+		cp .gitmodules .gitmodules.bak &&
+		echo "	value = \"" >>.gitmodules &&
+		git add .gitmodules &&
+		mv .gitmodules.bak .gitmodules &&
+		git commit -m "add error" &&
+		test-submodule-config \
+			HEAD b \
+			HEAD submodule \
+				>actual &&
+		test_cmp expect_error actual
+	)
+'
+
+test_done
diff --git a/test-submodule-config.c b/test-submodule-config.c
new file mode 100644
index 0000000..f3c3918
--- /dev/null
+++ b/test-submodule-config.c
@@ -0,0 +1,66 @@
+#include "cache.h"
+#include "submodule-config.h"
+
+static void die_usage(int argc, char **argv, const char *msg)
+{
+	fprintf(stderr, "%s\n", msg);
+	fprintf(stderr, "Usage: %s [<commit> <submodulepath>] ...\n", argv[0]);
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	char **arg = argv;
+	int my_argc = argc;
+	int output_url = 0;
+	int lookup_name = 0;
+
+	arg++;
+	my_argc--;
+	while (starts_with(arg[0], "--")) {
+		if (!strcmp(arg[0], "--url"))
+			output_url = 1;
+		if (!strcmp(arg[0], "--name"))
+			lookup_name = 1;
+		arg++;
+		my_argc--;
+	}
+
+	if (my_argc % 2 != 0)
+		die_usage(argc, argv, "Wrong number of arguments.");
+
+	while (*arg) {
+		unsigned char commit_sha1[20];
+		const struct submodule *submodule;
+		const char *commit;
+		const char *path_or_name;
+
+		commit = arg[0];
+		path_or_name = arg[1];
+
+		if (commit[0] == '\0')
+			hashcpy(commit_sha1, null_sha1);
+		else if (get_sha1(commit, commit_sha1) < 0)
+			die_usage(argc, argv, "Commit not found.");
+
+		if (lookup_name) {
+			submodule = submodule_from_name(commit_sha1, path_or_name);
+		} else
+			submodule = submodule_from_path(commit_sha1, path_or_name);
+		if (!submodule)
+			die_usage(argc, argv, "Submodule not found.");
+
+		if (output_url)
+			printf("Submodule url: '%s' for path '%s'\n",
+					submodule->url, submodule->path);
+		else
+			printf("Submodule name: '%s' for path '%s'\n",
+					submodule->name, submodule->path);
+
+		arg += 2;
+	}
+
+	submodule_free();
+
+	return 0;
+}
-- 
2.5.0.330.g130be8e.dirty

^ permalink raw reply related	[relevance 14%]

* [PATCH 3/7] submodule: use new config API for worktree configurations
  2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
  2015-08-18  0:21 14% ` [PATCH 1/7] submodule: implement a config API for lookup of .gitmodules values Stefan Beller
  2015-08-18  0:21 11% ` [PATCH 2/7] submodule: extract functions for config set and lookup Stefan Beller
@ 2015-08-18  0:21 23% ` Stefan Beller
  2015-08-18  0:22 26% ` [PATCH 4/7] submodule: Allow errornous values for the fetchrecursesubmodules option Stefan Beller
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:21 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

From: Heiko Voigt <hvoigt@hvoigt.net>

We remove the extracted functions and directly parse into and read out
of the cache. This allows us to have one unified way of accessing
submodule configuration values specific to single submodules. Regardless
whether we need to access a configuration from history or from the
worktree.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 Documentation/technical/api-submodule-config.txt |  19 ++-
 builtin/checkout.c                               |   1 +
 diff.c                                           |   1 +
 submodule-config.c                               |  12 ++
 submodule-config.h                               |   1 +
 submodule.c                                      | 160 ++++-------------------
 submodule.h                                      |   1 -
 t/t7411-submodule-config.sh                      |  37 +++++-
 test-submodule-config.c                          |  10 ++
 9 files changed, 104 insertions(+), 138 deletions(-)

diff --git a/Documentation/technical/api-submodule-config.txt b/Documentation/technical/api-submodule-config.txt
index 1fbde41..941fa17 100644
--- a/Documentation/technical/api-submodule-config.txt
+++ b/Documentation/technical/api-submodule-config.txt
@@ -10,10 +10,18 @@ submodule path or name.
 Usage
 -----
 
+To initialize the cache with configurations from the worktree the caller
+typically first calls `gitmodules_config()` to read values from the
+worktree .gitmodules and then to overlay the local git config values
+`parse_submodule_config_option()` from the config parsing
+infrastructure.
+
 The caller can look up information about submodules by using the
 `submodule_from_path()` or `submodule_from_name()` functions. They return
 a `struct submodule` which contains the values. The API automatically
-initializes and allocates the needed infrastructure on-demand.
+initializes and allocates the needed infrastructure on-demand. If the
+caller does only want to lookup values from revisions the initialization
+can be skipped.
 
 If the internal cache might grow too big or when the caller is done with
 the API, all internally cached values can be freed with submodule_free().
@@ -34,6 +42,11 @@ Functions
 
 	Use these to free the internally cached values.
 
+`int parse_submodule_config_option(const char *var, const char *value)`::
+
+	Can be passed to the config parsing infrastructure to parse
+	local (worktree) submodule configurations.
+
 `const struct submodule *submodule_from_path(const unsigned char *commit_sha1, const char *path)`::
 
 	Lookup values for one submodule by its commit_sha1 and path.
@@ -42,4 +55,8 @@ Functions
 
 	The same as above but lookup by name.
 
+If given the null_sha1 as commit_sha1 the local configuration of a
+submodule will be returned (e.g. consolidated values from local git
+configuration and the .gitmodules file in the worktree).
+
 For an example usage see test-submodule-config.c.
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 9ff5ca4..7ea533e 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -18,6 +18,7 @@
 #include "xdiff-interface.h"
 #include "ll-merge.h"
 #include "resolve-undo.h"
+#include "submodule-config.h"
 #include "submodule.h"
 
 static const char * const checkout_usage[] = {
diff --git a/diff.c b/diff.c
index 7deac90..8b382c2 100644
--- a/diff.c
+++ b/diff.c
@@ -13,6 +13,7 @@
 #include "utf8.h"
 #include "userdiff.h"
 #include "sigchain.h"
+#include "submodule-config.h"
 #include "submodule.h"
 #include "ll-merge.h"
 #include "string-list.h"
diff --git a/submodule-config.c b/submodule-config.c
index ea82edb..c64faf3 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -422,6 +422,18 @@ static void ensure_cache_init(void)
 	is_cache_init = 1;
 }
 
+int parse_submodule_config_option(const char *var, const char *value)
+{
+	struct parse_config_parameter parameter;
+	parameter.cache = &cache;
+	parameter.commit_sha1 = NULL;
+	parameter.gitmodules_sha1 = null_sha1;
+	parameter.overwrite = 1;
+
+	ensure_cache_init();
+	return parse_config(var, value, &parameter);
+}
+
 const struct submodule *submodule_from_name(const unsigned char *commit_sha1,
 		const char *name)
 {
diff --git a/submodule-config.h b/submodule-config.h
index cd68030..5fe44ce 100644
--- a/submodule-config.h
+++ b/submodule-config.h
@@ -18,6 +18,7 @@ struct submodule {
 	unsigned char gitmodules_sha1[20];
 };
 
+int parse_submodule_config_option(const char *var, const char *value);
 const struct submodule *submodule_from_name(const unsigned char *commit_sha1,
 		const char *name);
 const struct submodule *submodule_from_path(const unsigned char *commit_sha1,
diff --git a/submodule.c b/submodule.c
index 307fa43..a382677 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "submodule-config.h"
 #include "submodule.h"
 #include "dir.h"
 #include "diff.h"
@@ -12,9 +13,6 @@
 #include "argv-array.h"
 #include "blob.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 int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
 static struct string_list changed_submodule_paths;
 static int initialized_fetch_ref_tips;
@@ -41,77 +39,6 @@ static int gitmodules_is_unmerged;
  */
 static int gitmodules_is_modified;
 
-static const char *get_name_for_path(const char *path)
-{
-	struct string_list_item *path_option;
-	if (path == NULL) {
-		if (config_name_for_path.nr > 0)
-			return config_name_for_path.items[0].util;
-		else
-			return NULL;
-	}
-	path_option = unsorted_string_list_lookup(&config_name_for_path, path);
-	if (!path_option)
-		return NULL;
-	return path_option->util;
-}
-
-static void set_name_for_path(const char *path, const char *name, int namelen)
-{
-	struct string_list_item *config;
-	config = unsorted_string_list_lookup(&config_name_for_path, path);
-	if (config)
-		free(config->util);
-	else
-		config = string_list_append(&config_name_for_path, xstrdup(path));
-	config->util = xmemdupz(name, namelen);
-}
-
-static const char *get_ignore_for_name(const char *name)
-{
-	struct string_list_item *ignore_option;
-	ignore_option = unsorted_string_list_lookup(&config_ignore_for_name, name);
-	if (!ignore_option)
-		return NULL;
-
-	return ignore_option->util;
-}
-
-static void set_ignore_for_name(const char *name, int namelen, const char *ignore)
-{
-	struct string_list_item *config;
-	char *name_cstr = xmemdupz(name, namelen);
-	config = unsorted_string_list_lookup(&config_ignore_for_name, name_cstr);
-	if (config) {
-		free(config->util);
-		free(name_cstr);
-	} else
-		config = string_list_append(&config_ignore_for_name, name_cstr);
-	config->util = xstrdup(ignore);
-}
-
-static int get_fetch_recurse_for_name(const char *name)
-{
-	struct string_list_item *fetch_recurse;
-	fetch_recurse = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name);
-	if (!fetch_recurse)
-		return RECURSE_SUBMODULES_NONE;
-
-	return (intptr_t) fetch_recurse->util;
-}
-
-static void set_fetch_recurse_for_name(const char *name, int namelen, int fetch_recurse)
-{
-	struct string_list_item *config;
-	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, name_cstr);
-	else
-		free(name_cstr);
-	config->util = (void *)(intptr_t) fetch_recurse;
-}
-
 int is_staging_gitmodules_ok(void)
 {
 	return !gitmodules_is_modified;
@@ -125,7 +52,7 @@ int is_staging_gitmodules_ok(void)
 int update_path_in_gitmodules(const char *oldpath, const char *newpath)
 {
 	struct strbuf entry = STRBUF_INIT;
-	const char *path;
+	const struct submodule *submodule;
 
 	if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */
 		return -1;
@@ -133,13 +60,13 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
 	if (gitmodules_is_unmerged)
 		die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
 
-	path = get_name_for_path(oldpath);
-	if (!path) {
+	submodule = submodule_from_path(null_sha1, oldpath);
+	if (!submodule || !submodule->name) {
 		warning(_("Could not find section in .gitmodules where path=%s"), oldpath);
 		return -1;
 	}
 	strbuf_addstr(&entry, "submodule.");
-	strbuf_addstr(&entry, path);
+	strbuf_addstr(&entry, submodule->name);
 	strbuf_addstr(&entry, ".path");
 	if (git_config_set_in_file(".gitmodules", entry.buf, newpath) < 0) {
 		/* Maybe the user already did that, don't error out here */
@@ -159,7 +86,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
 int remove_path_from_gitmodules(const char *path)
 {
 	struct strbuf sect = STRBUF_INIT;
-	const char *path_option;
+	const struct submodule *submodule;
 
 	if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */
 		return -1;
@@ -167,13 +94,13 @@ int remove_path_from_gitmodules(const char *path)
 	if (gitmodules_is_unmerged)
 		die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
 
-	path_option = get_name_for_path(path);
-	if (!path_option) {
+	submodule = submodule_from_path(null_sha1, path);
+	if (!submodule || !submodule->name) {
 		warning(_("Could not find section in .gitmodules where path=%s"), path);
 		return -1;
 	}
 	strbuf_addstr(&sect, "submodule.");
-	strbuf_addstr(&sect, path_option);
+	strbuf_addstr(&sect, submodule->name);
 	if (git_config_rename_section_in_file(".gitmodules", sect.buf, NULL) < 0) {
 		/* Maybe the user already did that, don't error out here */
 		warning(_("Could not remove .gitmodules entry for %s"), path);
@@ -235,11 +162,10 @@ done:
 void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
 					     const char *path)
 {
-	const char *name = get_name_for_path(path);
-	if (name) {
-		const char *ignore = get_ignore_for_name(name);
-		if (ignore)
-			handle_ignore_submodules_arg(diffopt, ignore);
+	const struct submodule *submodule = submodule_from_path(null_sha1, path);
+	if (submodule) {
+		if (submodule->ignore)
+			handle_ignore_submodules_arg(diffopt, submodule->ignore);
 		else if (gitmodules_is_unmerged)
 			DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
 	}
@@ -288,42 +214,6 @@ void gitmodules_config(void)
 	}
 }
 
-int parse_submodule_config_option(const char *var, const char *value)
-{
-	const char *name, *key;
-	int namelen;
-
-	if (parse_config_key(var, "submodule", &name, &namelen, &key) < 0 || !name)
-		return 0;
-
-	if (!strcmp(key, "path")) {
-		if (!value)
-			return config_error_nonbool(var);
-
-		set_name_for_path(value, name, namelen);
-
-	} else if (!strcmp(key, "fetchrecursesubmodules")) {
-		int fetch_recurse = parse_fetch_recurse_submodules_arg(var, value);
-
-		set_fetch_recurse_for_name(name, namelen, fetch_recurse);
-
-	} else if (!strcmp(key, "ignore")) {
-
-		if (!value)
-			return config_error_nonbool(var);
-
-		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;
-		}
-
-		set_ignore_for_name(name, namelen, value);
-		return 0;
-	}
-	return 0;
-}
-
 void handle_ignore_submodules_arg(struct diff_options *diffopt,
 				  const char *arg)
 {
@@ -700,7 +590,7 @@ static void calculate_changed_submodule_paths(void)
 	struct argv_array argv = ARGV_ARRAY_INIT;
 
 	/* No need to check if there are no submodules configured */
-	if (!get_name_for_path(NULL))
+	if (!submodule_from_path(NULL, NULL))
 		return;
 
 	init_revisions(&rev, NULL);
@@ -747,7 +637,6 @@ int fetch_populated_submodules(const struct argv_array *options,
 	int i, result = 0;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	struct argv_array argv = ARGV_ARRAY_INIT;
-	const char *name_for_path;
 	const char *work_tree = get_git_work_tree();
 	if (!work_tree)
 		goto out;
@@ -772,23 +661,26 @@ int fetch_populated_submodules(const struct argv_array *options,
 		struct strbuf submodule_git_dir = STRBUF_INIT;
 		struct strbuf submodule_prefix = STRBUF_INIT;
 		const struct cache_entry *ce = active_cache[i];
-		const char *git_dir, *name, *default_argv;
+		const char *git_dir, *default_argv;
+		const struct submodule *submodule;
 
 		if (!S_ISGITLINK(ce->ce_mode))
 			continue;
 
-		name = ce->name;
-		name_for_path = get_name_for_path(ce->name);
-		if (name_for_path)
-			name = name_for_path;
+		submodule = submodule_from_path(null_sha1, ce->name);
+		if (!submodule)
+			submodule = submodule_from_name(null_sha1, ce->name);
 
 		default_argv = "yes";
 		if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
-			int fetch_recurse_option = get_fetch_recurse_for_name(name);
-			if (fetch_recurse_option != RECURSE_SUBMODULES_NONE) {
-				if (fetch_recurse_option == RECURSE_SUBMODULES_OFF)
+			if (submodule &&
+			    submodule->fetch_recurse !=
+						RECURSE_SUBMODULES_NONE) {
+				if (submodule->fetch_recurse ==
+						RECURSE_SUBMODULES_OFF)
 					continue;
-				if (fetch_recurse_option == RECURSE_SUBMODULES_ON_DEMAND) {
+				if (submodule->fetch_recurse ==
+						RECURSE_SUBMODULES_ON_DEMAND) {
 					if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
 						continue;
 					default_argv = "on-demand";
diff --git a/submodule.h b/submodule.h
index 920fef3..547219d 100644
--- a/submodule.h
+++ b/submodule.h
@@ -20,7 +20,6 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
 		const char *path);
 int submodule_config(const char *var, const char *value, void *cb);
 void gitmodules_config(void);
-int parse_submodule_config_option(const char *var, const char *value);
 void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
 int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
 void show_submodule_summary(FILE *f, const char *path,
diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh
index 2602bc5..7229978 100755
--- a/t/t7411-submodule-config.sh
+++ b/t/t7411-submodule-config.sh
@@ -5,8 +5,8 @@
 
 test_description='Test submodules config cache infrastructure
 
-This test verifies that parsing .gitmodules configuration directly
-from the database works.
+This test verifies that parsing .gitmodules configurations directly
+from the database and from the worktree works.
 '
 
 TEST_NO_CREATE_REPO=1
@@ -82,4 +82,37 @@ test_expect_success 'error in one submodule config lets continue' '
 	)
 '
 
+cat >super/expect_url <<EOF
+Submodule url: 'git@somewhere.else.net:a.git' for path 'b'
+Submodule url: 'git@somewhere.else.net:submodule.git' for path 'submodule'
+EOF
+
+cat >super/expect_local_path <<EOF
+Submodule name: 'a' for path 'c'
+Submodule name: 'submodule' for path 'submodule'
+EOF
+
+test_expect_success 'reading of local configuration' '
+	(cd super &&
+		old_a=$(git config submodule.a.url) &&
+		old_submodule=$(git config submodule.submodule.url) &&
+		git config submodule.a.url git@somewhere.else.net:a.git &&
+		git config submodule.submodule.url git@somewhere.else.net:submodule.git &&
+		test-submodule-config --url \
+			"" b \
+			"" submodule \
+				>actual &&
+		test_cmp expect_url actual &&
+		git config submodule.a.path c &&
+		test-submodule-config \
+			"" c \
+			"" submodule \
+				>actual &&
+		test_cmp expect_local_path actual &&
+		git config submodule.a.url $old_a &&
+		git config submodule.submodule.url $old_submodule &&
+		git config --unset submodule.a.path c
+	)
+'
+
 test_done
diff --git a/test-submodule-config.c b/test-submodule-config.c
index f3c3918..dab8c27 100644
--- a/test-submodule-config.c
+++ b/test-submodule-config.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "submodule-config.h"
+#include "submodule.h"
 
 static void die_usage(int argc, char **argv, const char *msg)
 {
@@ -8,6 +9,11 @@ static void die_usage(int argc, char **argv, const char *msg)
 	exit(1);
 }
 
+static int git_test_config(const char *var, const char *value, void *cb)
+{
+	return parse_submodule_config_option(var, value);
+}
+
 int main(int argc, char **argv)
 {
 	char **arg = argv;
@@ -29,6 +35,10 @@ int main(int argc, char **argv)
 	if (my_argc % 2 != 0)
 		die_usage(argc, argv, "Wrong number of arguments.");
 
+	setup_git_directory();
+	gitmodules_config();
+	git_config(git_test_config, NULL);
+
 	while (*arg) {
 		unsigned char commit_sha1[20];
 		const struct submodule *submodule;
-- 
2.5.0.330.g130be8e.dirty

^ permalink raw reply related	[relevance 23%]

* [PATCH 4/7] submodule: Allow errornous values for the fetchrecursesubmodules option
  2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
                   ` (2 preceding siblings ...)
  2015-08-18  0:21 23% ` [PATCH 3/7] submodule: use new config API for worktree configurations Stefan Beller
@ 2015-08-18  0:22 26% ` Stefan Beller
  2015-08-19 18:09  4%   ` Junio C Hamano
  2015-08-18  0:22 19% ` [PATCH 5/7] submodule: implement `module_list` as a builtin helper Stefan Beller
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 200+ results
From: Stefan Beller @ 2015-08-18  0:22 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

From: Heiko Voigt <hvoigt@hvoigt.net>

We should not die when reading the submodule config cache since the user
might not be able to get out of that situation when the configuration is
part of the history.

We should handle this condition later when the value is about to be
used.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 builtin/fetch.c             |  1 +
 submodule-config.c          | 29 ++++++++++++++++++++++++++++-
 submodule-config.h          |  1 +
 submodule.c                 | 15 ---------------
 submodule.h                 |  2 +-
 t/t7411-submodule-config.sh | 35 +++++++++++++++++++++++++++++++++++
 6 files changed, 66 insertions(+), 17 deletions(-)

diff --git a/builtin/fetch.c b/builtin/fetch.c
index df16d0a..ee1f1a9 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -11,6 +11,7 @@
 #include "run-command.h"
 #include "parse-options.h"
 #include "sigchain.h"
+#include "submodule-config.h"
 #include "submodule.h"
 #include "connected.h"
 #include "argv-array.h"
diff --git a/submodule-config.c b/submodule-config.c
index c64faf3..393de53 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -204,6 +204,30 @@ static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,
 	return submodule;
 }
 
+static int parse_fetch_recurse(const char *opt, const char *arg,
+			       int die_on_error)
+{
+	switch (git_config_maybe_bool(opt, arg)) {
+	case 1:
+		return RECURSE_SUBMODULES_ON;
+	case 0:
+		return RECURSE_SUBMODULES_OFF;
+	default:
+		if (!strcmp(arg, "on-demand"))
+			return RECURSE_SUBMODULES_ON_DEMAND;
+
+		if (die_on_error)
+			die("bad %s argument: %s", opt, arg);
+		else
+			return RECURSE_SUBMODULES_ERROR;
+	}
+}
+
+int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
+{
+	return parse_fetch_recurse(opt, arg, 1);
+}
+
 static void warn_multiple_config(const unsigned char *commit_sha1,
 				 const char *name, const char *option)
 {
@@ -255,6 +279,8 @@ static int parse_config(const char *var, const char *value, void *data)
 		submodule->path = strbuf_detach(&path, NULL);
 		cache_put_path(me->cache, submodule);
 	} else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
+		/* when parsing worktree configurations we can die early */
+		int die_on_error = is_null_sha1(me->gitmodules_sha1);
 		if (!me->overwrite &&
 		    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) {
 			warn_multiple_config(me->commit_sha1, submodule->name,
@@ -262,7 +288,8 @@ static int parse_config(const char *var, const char *value, void *data)
 			goto release_return;
 		}
 
-		submodule->fetch_recurse = parse_fetch_recurse_submodules_arg(var, value);
+		submodule->fetch_recurse = parse_fetch_recurse(var, value,
+								die_on_error);
 	} else if (!strcmp(item.buf, "ignore")) {
 		struct strbuf ignore = STRBUF_INIT;
 		if (!me->overwrite && submodule->ignore != NULL) {
diff --git a/submodule-config.h b/submodule-config.h
index 5fe44ce..9061e4e 100644
--- a/submodule-config.h
+++ b/submodule-config.h
@@ -18,6 +18,7 @@ struct submodule {
 	unsigned char gitmodules_sha1[20];
 };
 
+int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
 int parse_submodule_config_option(const char *var, const char *value);
 const struct submodule *submodule_from_name(const unsigned char *commit_sha1,
 		const char *name);
diff --git a/submodule.c b/submodule.c
index a382677..9fcc86f 100644
--- a/submodule.c
+++ b/submodule.c
@@ -288,21 +288,6 @@ static void print_submodule_summary(struct rev_info *rev, FILE *f,
 	strbuf_release(&sb);
 }
 
-int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
-{
-	switch (git_config_maybe_bool(opt, arg)) {
-	case 1:
-		return RECURSE_SUBMODULES_ON;
-	case 0:
-		return RECURSE_SUBMODULES_OFF;
-	default:
-		if (!strcmp(arg, "on-demand"))
-			return RECURSE_SUBMODULES_ON_DEMAND;
-		/* TODO: remove the die for history parsing here */
-		die("bad %s argument: %s", opt, arg);
-	}
-}
-
 void show_submodule_summary(FILE *f, const char *path,
 		const char *line_prefix,
 		unsigned char one[20], unsigned char two[20],
diff --git a/submodule.h b/submodule.h
index 547219d..5507c3d 100644
--- a/submodule.h
+++ b/submodule.h
@@ -5,6 +5,7 @@ struct diff_options;
 struct argv_array;
 
 enum {
+	RECURSE_SUBMODULES_ERROR = -3,
 	RECURSE_SUBMODULES_NONE = -2,
 	RECURSE_SUBMODULES_ON_DEMAND = -1,
 	RECURSE_SUBMODULES_OFF = 0,
@@ -21,7 +22,6 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
 int submodule_config(const char *var, const char *value, void *cb);
 void gitmodules_config(void);
 void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
-int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
 void show_submodule_summary(FILE *f, const char *path,
 		const char *line_prefix,
 		unsigned char one[20], unsigned char two[20],
diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh
index 7229978..fc97c33 100755
--- a/t/t7411-submodule-config.sh
+++ b/t/t7411-submodule-config.sh
@@ -115,4 +115,39 @@ test_expect_success 'reading of local configuration' '
 	)
 '
 
+cat >super/expect_fetchrecurse_die.err <<EOF
+fatal: bad submodule.submodule.fetchrecursesubmodules argument: blabla
+EOF
+
+test_expect_success 'local error in fetchrecursesubmodule dies early' '
+	(cd super &&
+		git config submodule.submodule.fetchrecursesubmodules blabla &&
+		test_must_fail test-submodule-config \
+			"" b \
+			"" submodule \
+				>actual.out 2>actual.err &&
+		touch expect_fetchrecurse_die.out &&
+		test_cmp expect_fetchrecurse_die.out actual.out  &&
+		test_cmp expect_fetchrecurse_die.err actual.err  &&
+		git config --unset submodule.submodule.fetchrecursesubmodules
+	)
+'
+
+test_expect_success 'error in history in fetchrecursesubmodule lets continue' '
+	(cd super &&
+		git config -f .gitmodules \
+			submodule.submodule.fetchrecursesubmodules blabla &&
+		git add .gitmodules &&
+		git config --unset -f .gitmodules \
+			submodule.submodule.fetchrecursesubmodules &&
+		git commit -m "add error in fetchrecursesubmodules" &&
+		test-submodule-config \
+			HEAD b \
+			HEAD submodule \
+				>actual &&
+		test_cmp expect_error actual  &&
+		git reset --hard HEAD^
+	)
+'
+
 test_done
-- 
2.5.0.330.g130be8e.dirty

^ permalink raw reply related	[relevance 26%]

* [PATCH 7/7] submodule: implement `module_clone` as a builtin helper
  2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
                   ` (5 preceding siblings ...)
  2015-08-18  0:22 24% ` [PATCH 6/7] submodule: implement `module_name` " Stefan Beller
@ 2015-08-18  0:22 20% ` Stefan Beller
  2015-08-18  0:26  7%   ` Stefan Beller
  2015-08-18 22:13 20%   ` Stefan Beller
  2015-08-18  0:38  7% ` [PATCH 0/7] Submodule improvements Stefan Beller
  7 siblings, 2 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:22 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

`module_clone` is part of the update command, which I want to convert
to C next.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 builtin/submodule--helper.c | 161 +++++++++++++++++++++++++++++++++++++++++++-
 git-submodule.sh            |  78 +--------------------
 2 files changed, 162 insertions(+), 77 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 80d13f5..44ff935 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -8,6 +8,7 @@
 #include "submodule.h"
 #include "submodule-config.h"
 #include "string-list.h"
+#include "run-command.h"
 
 static const struct cache_entry **ce_entries;
 static int ce_alloc, ce_used;
@@ -124,6 +125,156 @@ static int module_name(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static int clone_submodule(const char *path, const char *gitdir, const char *url,
+			   const char *depth, const char *reference, int quiet)
+{
+	struct child_process cp;
+	child_process_init(&cp);
+
+	argv_array_push(&cp.args, "clone");
+	argv_array_push(&cp.args, "--no-checkout");
+	if (quiet)
+		argv_array_push(&cp.args, "--quiet");
+	if (depth && strcmp(depth, "")) {
+		argv_array_push(&cp.args, "--depth");
+		argv_array_push(&cp.args, depth);
+	}
+	if (reference && strcmp(reference, "")) {
+		argv_array_push(&cp.args, "--reference");
+		argv_array_push(&cp.args, reference);
+	}
+	if (gitdir) {
+		argv_array_push(&cp.args, "--separate-git-dir");
+		argv_array_push(&cp.args, gitdir);
+	}
+	argv_array_push(&cp.args, url);
+	argv_array_push(&cp.args, path);
+
+	cp.git_cmd = 1;
+	cp.env = local_repo_env;
+
+	cp.no_stdin = 1;
+	cp.no_stdout = 1;
+	cp.no_stderr = 1;
+	return run_command(&cp);
+}
+
+/*
+ * Clone a submodule
+ *
+ * $1 = submodule path
+ * $2 = submodule name
+ * $3 = URL to clone
+ * $4 = reference repository to reuse (empty for independent)
+ * $5 = depth argument for shallow clones (empty for deep)
+ *
+ * Prior to calling, cmd_update checks that a possibly existing
+ * path is not a git repository.
+ * Likewise, cmd_add checks that path does not exist at all,
+ * since it is the location of a new submodule.
+ */
+static int module_clone(int argc, const char **argv, const char *prefix)
+{
+	const char *path = NULL, *name = NULL, *url = NULL, *reference = NULL, *depth = NULL;
+	int quiet = 0;
+	FILE *submodule_dot_git;
+	const char *sm_gitdir, *p;
+	struct strbuf rel_path = STRBUF_INIT;
+	struct strbuf sb = STRBUF_INIT;
+
+	struct option module_update_options[] = {
+		OPT_STRING(0, "prefix", &alternative_path,
+			   N_("path"),
+			   N_("alternative anchor for relative paths")),
+		OPT_STRING(0, "path", &path,
+			   N_("path"),
+			   N_("where the new submodule will be cloned to")),
+		OPT_STRING(0, "name", &name,
+			   N_("string"),
+			   N_("name of the new submodule")),
+		OPT_STRING(0, "url", &url,
+			   N_("string"),
+			   N_("url where to clone the submodule from")),
+		OPT_STRING(0, "reference", &reference,
+			   N_("string"),
+			   N_("reference repository")),
+		OPT_STRING(0, "depth", &depth,
+			   N_("string"),
+			   N_("depth for shallow clones")),
+		OPT_END()
+	};
+
+	static const char * const git_submodule_helper_usage[] = {
+		N_("git submodule--helper update [--prefix=<path>] [--quiet] [--remote] [-N|--no-fetch]"
+		   "[-f|--force] [--rebase|--merge] [--reference <repository>]"
+		   "[--depth <depth>] [--recursive] [--] [<path>...]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, module_update_options,
+			     git_submodule_helper_usage, 0);
+
+	if (getenv("GIT_QUIET"))
+		quiet = 1;
+
+	strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
+	sm_gitdir = strbuf_detach(&sb, NULL);
+	strbuf_reset(&sb);
+
+	if (!file_exists(sm_gitdir)) {
+		safe_create_leading_directories_const(sm_gitdir);
+		if (clone_submodule(path, sm_gitdir, url, depth, reference, quiet))
+			die(N_("Clone of '%s' into submodule path '%s' failed"),
+			    url, path);
+	} else {
+		safe_create_leading_directories_const(path);
+		unlink(sm_gitdir);
+	}
+
+	/* Write a .git file in the submodule to redirect to the superproject. */
+	const char *t;
+	if (alternative_path && !strcmp(alternative_path, "")) {
+		t = relative_path(path, alternative_path, &sb);
+		strbuf_reset(&sb);
+	} else
+		t = path;
+
+	if (safe_create_leading_directories_const(t) < 0)
+		die("Could not create directory '%s'", t);
+
+	strbuf_addf(&sb, "%s/.git", t);
+
+	if (safe_create_leading_directories_const(sb.buf) < 0)
+		die(_("could not create leading directories of '%s'"), sb.buf);
+	submodule_dot_git = fopen(sb.buf, "w");
+	if (!submodule_dot_git)
+		die ("Cannot open file '%s': %s", sb.buf, strerror(errno)	);
+
+	fprintf(submodule_dot_git, "gitdir: %s\n",
+		relative_path(sm_gitdir, path, &rel_path));
+	if (fclose(submodule_dot_git))
+		die("Could not close file %s", sb.buf);
+	strbuf_reset(&sb);
+
+	/* Redirect the worktree of the submodule in the superprojects config */
+	if (!is_absolute_path(sm_gitdir)) {
+		char *s = (char*)sm_gitdir;
+		strbuf_addf(&sb, "%s/%s", xgetcwd(), sm_gitdir);
+		sm_gitdir = strbuf_detach(&sb, NULL);
+		strbuf_reset(&sb);
+		free(s);
+	}
+	strbuf_addf(&sb, "%s/%s", xgetcwd(), path);
+	t = relative_path(sb.buf, sm_gitdir, &rel_path);
+
+	p = git_pathdup_submodule(path, "config");
+	if (!p)
+		die("Could not get submodule directory for '%s'", path);
+	git_config_set_in_file(p, "core.worktree", t);
+	strbuf_release(&sb);
+	return 0;
+}
+
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 {
 	if (argc < 2)
@@ -135,6 +286,14 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 	if (!strcmp(argv[1], "module_name"))
 		return module_name(argc - 2, argv + 2, prefix);
 
+	if (!strcmp(argv[1], "module_clone"))
+		return module_clone(argc - 1, argv + 1, prefix);
+	if (!strcmp(argv[1], "test")) {
+		struct strbuf sb = STRBUF_INIT;
+
+		relative_path(".git/modules/example", "init", &sb);
+		return 0;
+	}
 usage:
-	usage("git submodule--helper [module_list module_name]\n");
+	usage("git submodule--helper [module_list module_name module_clone]\n");
 }
diff --git a/git-submodule.sh b/git-submodule.sh
index e6ff38d..6e8561e 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -178,80 +178,6 @@ get_submodule_config () {
 	printf '%s' "${value:-$default}"
 }
 
-#
-# Clone a submodule
-#
-# $1 = submodule path
-# $2 = submodule name
-# $3 = URL to clone
-# $4 = reference repository to reuse (empty for independent)
-# $5 = depth argument for shallow clones (empty for deep)
-#
-# Prior to calling, cmd_update checks that a possibly existing
-# path is not a git repository.
-# Likewise, cmd_add checks that path does not exist at all,
-# since it is the location of a new submodule.
-#
-module_clone()
-{
-	sm_path=$1
-	name=$2
-	url=$3
-	reference="$4"
-	depth="$5"
-	quiet=
-	if test -n "$GIT_QUIET"
-	then
-		quiet=-q
-	fi
-
-	gitdir=
-	gitdir_base=
-	base_name=$(dirname "$name")
-
-	gitdir=$(git rev-parse --git-dir)
-	gitdir_base="$gitdir/modules/$base_name"
-	gitdir="$gitdir/modules/$name"
-
-	if test -d "$gitdir"
-	then
-		mkdir -p "$sm_path"
-		rm -f "$gitdir/index"
-	else
-		mkdir -p "$gitdir_base"
-		(
-			clear_local_git_env
-			git clone $quiet ${depth:+"$depth"} -n ${reference:+"$reference"} \
-				--separate-git-dir "$gitdir" "$url" "$sm_path"
-		) ||
-		die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
-	fi
-
-	# We already are at the root of the work tree but cd_to_toplevel will
-	# resolve any symlinks that might be present in $PWD
-	a=$(cd_to_toplevel && cd "$gitdir" && pwd)/
-	b=$(cd_to_toplevel && cd "$sm_path" && pwd)/
-	# Remove all common leading directories after a sanity check
-	if test "${a#$b}" != "$a" || test "${b#$a}" != "$b"; then
-		die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")"
-	fi
-	while test "${a%%/*}" = "${b%%/*}"
-	do
-		a=${a#*/}
-		b=${b#*/}
-	done
-	# Now chop off the trailing '/'s that were added in the beginning
-	a=${a%/}
-	b=${b%/}
-
-	# Turn each leading "*/" component into "../"
-	rel=$(printf '%s\n' "$b" | sed -e 's|[^/][^/]*|..|g')
-	printf '%s\n' "gitdir: $rel/$a" >"$sm_path/.git"
-
-	rel=$(printf '%s\n' "$a" | sed -e 's|[^/][^/]*|..|g')
-	(clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
-}
-
 isnumber()
 {
 	n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
@@ -412,7 +338,7 @@ Use -f if you really want to add it." >&2
 				echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
 			fi
 		fi
-		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" || exit
+		git submodule--helper module_clone --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" --reference "$reference_path" --depth "$depth" || exit
 		(
 			clear_local_git_env
 			cd "$sm_path" &&
@@ -774,7 +700,7 @@ Maybe you want to use 'update --init'?")"
 
 		if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
 		then
-			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
+			git submodule--helper module_clone --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
 			cloned_modules="$cloned_modules;$name"
 			subsha1=
 		else
-- 
2.5.0.330.g130be8e.dirty

^ permalink raw reply related	[relevance 20%]

* [PATCH 6/7] submodule: implement `module_name` as a builtin helper
  2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
                   ` (4 preceding siblings ...)
  2015-08-18  0:22 19% ` [PATCH 5/7] submodule: implement `module_list` as a builtin helper Stefan Beller
@ 2015-08-18  0:22 24% ` Stefan Beller
  2015-08-18  0:22 20% ` [PATCH 7/7] submodule: implement `module_clone` " Stefan Beller
  2015-08-18  0:38  7% ` [PATCH 0/7] Submodule improvements Stefan Beller
  7 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:22 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

This implements the helper `module_name` in C instead of shell,
yielding a nice performance boost.

Before this patch, I measured a time (best out of three):

  $ time ./t7400-submodule-basic.sh  >/dev/null
    real	0m11.066s
    user	0m3.348s
    sys	0m8.534s

With this patch applied I measured (also best out of three)

  $ time ./t7400-submodule-basic.sh  >/dev/null
    real	0m10.063s
    user	0m3.044s
    sys	0m7.487s

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 builtin/submodule--helper.c | 28 +++++++++++++++++++++++++++-
 git-submodule.sh            | 32 +++++++-------------------------
 2 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 610ec51..80d13f5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -5,6 +5,9 @@
 #include "pathspec.h"
 #include "dir.h"
 #include "utf8.h"
+#include "submodule.h"
+#include "submodule-config.h"
+#include "string-list.h"
 
 static const struct cache_entry **ce_entries;
 static int ce_alloc, ce_used;
@@ -101,6 +104,26 @@ static int module_list(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static int module_name(int argc, const char **argv, const char *prefix)
+{
+	const char *name;
+	const struct submodule *sub;
+
+	if (argc != 1)
+		usage("git submodule--helper module_name <path>\n");
+
+	gitmodules_config();
+	sub = submodule_from_path(null_sha1, argv[0]);
+
+	if (!sub)
+		die("No submodule mapping found in .gitmodules for path '%s'", argv[0]);
+
+	name = sub->name;
+	printf("%s\n", name);
+
+	return 0;
+}
+
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 {
 	if (argc < 2)
@@ -109,6 +132,9 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 	if (!strcmp(argv[1], "module_list"))
 		return module_list(argc - 1, argv + 1, prefix);
 
+	if (!strcmp(argv[1], "module_name"))
+		return module_name(argc - 2, argv + 2, prefix);
+
 usage:
-	usage("git submodule--helper module_list\n");
+	usage("git submodule--helper [module_list module_name]\n");
 }
diff --git a/git-submodule.sh b/git-submodule.sh
index af9ecef..e6ff38d 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -178,24 +178,6 @@ get_submodule_config () {
 	printf '%s' "${value:-$default}"
 }
 
-
-#
-# Map submodule path to submodule name
-#
-# $1 = path
-#
-module_name()
-{
-	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
-	sm_path="$1"
-	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
-	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
-		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
-	test -z "$name" &&
-	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
-	printf '%s\n' "$name"
-}
-
 #
 # Clone a submodule
 #
@@ -498,7 +480,7 @@ cmd_foreach()
 		then
 			displaypath=$(relative_path "$sm_path")
 			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
-			name=$(module_name "$sm_path")
+			name=$(git submodule--helper module_name "$sm_path")
 			(
 				prefix="$prefix$sm_path/"
 				clear_local_git_env
@@ -554,7 +536,7 @@ cmd_init()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -636,7 +618,7 @@ cmd_deinit()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 
 		displaypath=$(relative_path "$sm_path")
 
@@ -758,7 +740,7 @@ cmd_update()
 			echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 			continue
 		fi
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		branch=$(get_submodule_config "$name" branch master)
 		if ! test -z "$update"
@@ -1022,7 +1004,7 @@ cmd_summary() {
 			# Respect the ignore setting for --for-status.
 			if test -n "$for_status"
 			then
-				name=$(module_name "$sm_path")
+				name=$(git submodule--helper module_name "$sm_path")
 				ignore_config=$(get_submodule_config "$name" ignore none)
 				test $status != A && test $ignore_config = all && continue
 			fi
@@ -1184,7 +1166,7 @@ cmd_status()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path") || exit
+		name=$(git submodule--helper module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
 		displaypath=$(relative_path "$prefix$sm_path")
 		if test "$stage" = U
@@ -1261,7 +1243,7 @@ cmd_sync()
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
-		name=$(module_name "$sm_path")
+		name=$(git submodule--helper module_name "$sm_path")
 		url=$(git config -f .gitmodules --get submodule."$name".url)
 
 		# Possibly a url relative to parent
-- 
2.5.0.330.g130be8e.dirty

^ permalink raw reply related	[relevance 24%]

* [PATCH 5/7] submodule: implement `module_list` as a builtin helper
  2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
                   ` (3 preceding siblings ...)
  2015-08-18  0:22 26% ` [PATCH 4/7] submodule: Allow errornous values for the fetchrecursesubmodules option Stefan Beller
@ 2015-08-18  0:22 19% ` Stefan Beller
  2015-08-18  0:22 24% ` [PATCH 6/7] submodule: implement `module_name` " Stefan Beller
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:22 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

Most of the submodule operations work on a set of submodules.
Calculating and using this set is usually done via:

       module_list "$@" | {
           while read mode sha1 stage sm_path
           do
                # the actual operation
           done
       }

Currently the function `module_list` is implemented in the
git-submodule.sh as a shell script wrapping a perl script.
The rewrite is in C, such that it is faster and can later be
easily adapted when other functions are rewritten in C.

git-submodule.sh similar to the builtin commands will navigate
to the top most directory of the repository and keeping the
subdirectories as a variable. As the helper is called from
within the git-submodule.sh script, we are already navigated
to the root level, but the path arguments are stil relative
to the subdirectory we were in when calling git-submodule.sh.
That's why there is a `--prefix` option pointing to an alternative
path where to anchor relative path arguments.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 .gitignore                  |   1 +
 Makefile                    |   1 +
 builtin.h                   |   1 +
 builtin/submodule--helper.c | 114 ++++++++++++++++++++++++++++++++++++++++++++
 git-submodule.sh            |  54 +++------------------
 git.c                       |   1 +
 6 files changed, 124 insertions(+), 48 deletions(-)
 create mode 100644 builtin/submodule--helper.c

diff --git a/.gitignore b/.gitignore
index 4fd81ba..1c2f832 100644
--- a/.gitignore
+++ b/.gitignore
@@ -155,6 +155,7 @@
 /git-status
 /git-stripspace
 /git-submodule
+/git-submodule--helper
 /git-svn
 /git-symbolic-ref
 /git-tag
diff --git a/Makefile b/Makefile
index 24b636d..d434e73 100644
--- a/Makefile
+++ b/Makefile
@@ -901,6 +901,7 @@ BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
 BUILTIN_OBJS += builtin/stripspace.o
+BUILTIN_OBJS += builtin/submodule--helper.o
 BUILTIN_OBJS += builtin/symbolic-ref.o
 BUILTIN_OBJS += builtin/tag.o
 BUILTIN_OBJS += builtin/unpack-file.o
diff --git a/builtin.h b/builtin.h
index 839483d..924e6c4 100644
--- a/builtin.h
+++ b/builtin.h
@@ -119,6 +119,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
 extern int cmd_status(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
+extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_tag(int argc, const char **argv, const char *prefix);
 extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
new file mode 100644
index 0000000..610ec51
--- /dev/null
+++ b/builtin/submodule--helper.c
@@ -0,0 +1,114 @@
+#include "builtin.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "quote.h"
+#include "pathspec.h"
+#include "dir.h"
+#include "utf8.h"
+
+static const struct cache_entry **ce_entries;
+static int ce_alloc, ce_used;
+static const char *alternative_path;
+
+static int module_list_compute(int argc, const char **argv,
+				const char *prefix,
+				struct pathspec *pathspec)
+{
+	int i;
+	char *max_prefix, *ps_matched = NULL;
+	int max_prefix_len;
+	parse_pathspec(pathspec, 0,
+		       PATHSPEC_PREFER_FULL |
+		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
+		       prefix, argv);
+
+	/* Find common prefix for all pathspec's */
+	max_prefix = common_prefix(pathspec);
+	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
+
+	if (pathspec->nr)
+		ps_matched = xcalloc(1, pathspec->nr);
+
+	if (read_cache() < 0)
+		die("index file corrupt");
+
+	for (i = 0; i < active_nr; i++) {
+		const struct cache_entry *ce = active_cache[i];
+
+		if (!match_pathspec(pathspec, ce->name, ce_namelen(ce),
+				    max_prefix_len, ps_matched,
+				    S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode)))
+			continue;
+
+		if (S_ISGITLINK(ce->ce_mode)) {
+			ALLOC_GROW(ce_entries, ce_used + 1, ce_alloc);
+			ce_entries[ce_used++] = ce;
+		}
+
+		while (i + 1 < active_nr && !strcmp(ce->name, active_cache[i + 1]->name))
+			/*
+			 * Skip entries with the same name in different stages
+			 * to make sure an entry is returned only once.
+			 */
+			i++;
+	}
+	free(max_prefix);
+
+	if (ps_matched && report_path_error(ps_matched, pathspec, prefix))
+		return -1;
+
+	return 0;
+}
+
+static int module_list(int argc, const char **argv, const char *prefix)
+{
+	int i;
+	static struct pathspec pathspec;
+
+	struct option module_list_options[] = {
+		OPT_STRING(0, "prefix", &alternative_path,
+			   N_("path"),
+			   N_("alternative anchor for relative paths")),
+		OPT_END()
+	};
+
+	static const char * const git_submodule_helper_usage[] = {
+		N_("git submodule--helper module_list [--prefix=<path>] [<path>...]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, module_list_options,
+			     git_submodule_helper_usage, 0);
+
+	if (module_list_compute(argc, argv, alternative_path
+					    ? alternative_path
+					    : prefix, &pathspec) < 0) {
+		printf("#unmatched\n");
+		return 1;
+	}
+
+	for (i = 0; i < ce_used; i++) {
+		const struct cache_entry *ce = ce_entries[i];
+
+		if (ce_stage(ce)) {
+			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
+		} else {
+			printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce));
+		}
+
+		utf8_fprintf(stdout, "%s\n", ce->name);
+	}
+	return 0;
+}
+
+int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
+{
+	if (argc < 2)
+		goto usage;
+
+	if (!strcmp(argv[1], "module_list"))
+		return module_list(argc - 1, argv + 1, prefix);
+
+usage:
+	usage("git submodule--helper module_list\n");
+}
diff --git a/git-submodule.sh b/git-submodule.sh
index 36797c3..af9ecef 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,48 +145,6 @@ relative_path ()
 	echo "$result$target"
 }
 
-#
-# Get submodule info for registered submodules
-# $@ = path to limit submodule list
-#
-module_list()
-{
-	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
-	(
-		git ls-files -z --error-unmatch --stage -- "$@" ||
-		echo "unmatched pathspec exists"
-	) |
-	@@PERL@@ -e '
-	my %unmerged = ();
-	my ($null_sha1) = ("0" x 40);
-	my @out = ();
-	my $unmatched = 0;
-	$/ = "\0";
-	while (<STDIN>) {
-		if (/^unmatched pathspec/) {
-			$unmatched = 1;
-			next;
-		}
-		chomp;
-		my ($mode, $sha1, $stage, $path) =
-			/^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
-		next unless $mode eq "160000";
-		if ($stage ne "0") {
-			if (!$unmerged{$path}++) {
-				push @out, "$mode $null_sha1 U\t$path\n";
-			}
-			next;
-		}
-		push @out, "$_\n";
-	}
-	if ($unmatched) {
-		print "#unmatched\n";
-	} else {
-		print for (@out);
-	}
-	'
-}
-
 die_if_unmatched ()
 {
 	if test "$1" = "#unmatched"
@@ -532,7 +490,7 @@ cmd_foreach()
 	# command in the subshell (and a recursive call to this function)
 	exec 3<&0
 
-	module_list |
+	git submodule--helper module_list --prefix "$wt_prefix"|
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -592,7 +550,7 @@ cmd_init()
 		shift
 	done
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -674,7 +632,7 @@ cmd_deinit()
 		die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
 	fi
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -790,7 +748,7 @@ cmd_update()
 	fi
 
 	cloned_modules=
-	module_list "$@" | {
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" | {
 	err=
 	while read mode sha1 stage sm_path
 	do
@@ -1222,7 +1180,7 @@ cmd_status()
 		shift
 	done
 
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
@@ -1299,7 +1257,7 @@ cmd_sync()
 		esac
 	done
 	cd_to_toplevel
-	module_list "$@" |
+	git submodule--helper module_list --prefix "$wt_prefix" "$@" |
 	while read mode sha1 stage sm_path
 	do
 		die_if_unmatched "$mode"
diff --git a/git.c b/git.c
index 55c327c..deecba0 100644
--- a/git.c
+++ b/git.c
@@ -469,6 +469,7 @@ static struct cmd_struct commands[] = {
 	{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 	{ "stripspace", cmd_stripspace },
+	{ "submodule--helper", cmd_submodule__helper, RUN_SETUP },
 	{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
 	{ "tag", cmd_tag, RUN_SETUP },
 	{ "unpack-file", cmd_unpack_file, RUN_SETUP },
-- 
2.5.0.330.g130be8e.dirty

^ permalink raw reply related	[relevance 19%]

* Re: [PATCH 7/7] submodule: implement `module_clone` as a builtin helper
  2015-08-18  0:22 20% ` [PATCH 7/7] submodule: implement `module_clone` " Stefan Beller
@ 2015-08-18  0:26  7%   ` Stefan Beller
  2015-08-18 22:13 20%   ` Stefan Beller
  1 sibling, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:26 UTC (permalink / raw)
  To: git@vger.kernel.org
  Cc: Junio C Hamano, Jens Lehmann, Heiko Voigt, Stefan Beller

On Mon, Aug 17, 2015 at 5:22 PM, Stefan Beller <sbeller@google.com> wrote:
> `module_clone` is part of the update command, which I want to convert
> to C next.
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>  builtin/submodule--helper.c | 161 +++++++++++++++++++++++++++++++++++++++++++-
>  git-submodule.sh            |  78 +--------------------
>  2 files changed, 162 insertions(+), 77 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 80d13f5..44ff935 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -8,6 +8,7 @@
>  #include "submodule.h"
>  #include "submodule-config.h"
>  #include "string-list.h"
> +#include "run-command.h"
>
>  static const struct cache_entry **ce_entries;
>  static int ce_alloc, ce_used;
> @@ -124,6 +125,156 @@ static int module_name(int argc, const char **argv, const char *prefix)
>         return 0;
>  }
>
> +static int clone_submodule(const char *path, const char *gitdir, const char *url,
> +                          const char *depth, const char *reference, int quiet)
> +{
> +       struct child_process cp;
> +       child_process_init(&cp);
> +
> +       argv_array_push(&cp.args, "clone");
> +       argv_array_push(&cp.args, "--no-checkout");
> +       if (quiet)
> +               argv_array_push(&cp.args, "--quiet");
> +       if (depth && strcmp(depth, "")) {
> +               argv_array_push(&cp.args, "--depth");
> +               argv_array_push(&cp.args, depth);
> +       }
> +       if (reference && strcmp(reference, "")) {
> +               argv_array_push(&cp.args, "--reference");
> +               argv_array_push(&cp.args, reference);
> +       }
> +       if (gitdir) {
> +               argv_array_push(&cp.args, "--separate-git-dir");
> +               argv_array_push(&cp.args, gitdir);
> +       }
> +       argv_array_push(&cp.args, url);
> +       argv_array_push(&cp.args, path);
> +
> +       cp.git_cmd = 1;
> +       cp.env = local_repo_env;
> +
> +       cp.no_stdin = 1;
> +       cp.no_stdout = 1;
> +       cp.no_stderr = 1;
> +       return run_command(&cp);
> +}
> +
> +/*
> + * Clone a submodule
> + *
> + * $1 = submodule path
> + * $2 = submodule name
> + * $3 = URL to clone
> + * $4 = reference repository to reuse (empty for independent)
> + * $5 = depth argument for shallow clones (empty for deep)
> + *
> + * Prior to calling, cmd_update checks that a possibly existing
> + * path is not a git repository.
> + * Likewise, cmd_add checks that path does not exist at all,
> + * since it is the location of a new submodule.
> + */
> +static int module_clone(int argc, const char **argv, const char *prefix)
> +{
> +       const char *path = NULL, *name = NULL, *url = NULL, *reference = NULL, *depth = NULL;
> +       int quiet = 0;
> +       FILE *submodule_dot_git;
> +       const char *sm_gitdir, *p;
> +       struct strbuf rel_path = STRBUF_INIT;
> +       struct strbuf sb = STRBUF_INIT;
> +
> +       struct option module_update_options[] = {
> +               OPT_STRING(0, "prefix", &alternative_path,
> +                          N_("path"),
> +                          N_("alternative anchor for relative paths")),
> +               OPT_STRING(0, "path", &path,
> +                          N_("path"),
> +                          N_("where the new submodule will be cloned to")),
> +               OPT_STRING(0, "name", &name,
> +                          N_("string"),
> +                          N_("name of the new submodule")),
> +               OPT_STRING(0, "url", &url,
> +                          N_("string"),
> +                          N_("url where to clone the submodule from")),
> +               OPT_STRING(0, "reference", &reference,
> +                          N_("string"),
> +                          N_("reference repository")),
> +               OPT_STRING(0, "depth", &depth,
> +                          N_("string"),
> +                          N_("depth for shallow clones")),
> +               OPT_END()
> +       };
> +
> +       static const char * const git_submodule_helper_usage[] = {
> +               N_("git submodule--helper update [--prefix=<path>] [--quiet] [--remote] [-N|--no-fetch]"
> +                  "[-f|--force] [--rebase|--merge] [--reference <repository>]"
> +                  "[--depth <depth>] [--recursive] [--] [<path>...]"),
> +               NULL
> +       };
> +
> +       argc = parse_options(argc, argv, prefix, module_update_options,
> +                            git_submodule_helper_usage, 0);
> +
> +       if (getenv("GIT_QUIET"))
> +               quiet = 1;
> +
> +       strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
> +       sm_gitdir = strbuf_detach(&sb, NULL);
> +       strbuf_reset(&sb);
> +
> +       if (!file_exists(sm_gitdir)) {
> +               safe_create_leading_directories_const(sm_gitdir);
> +               if (clone_submodule(path, sm_gitdir, url, depth, reference, quiet))
> +                       die(N_("Clone of '%s' into submodule path '%s' failed"),
> +                           url, path);
> +       } else {
> +               safe_create_leading_directories_const(path);
> +               unlink(sm_gitdir);
> +       }
> +
> +       /* Write a .git file in the submodule to redirect to the superproject. */
> +       const char *t;

declaration after statement.

> +       if (alternative_path && !strcmp(alternative_path, "")) {
> +               t = relative_path(path, alternative_path, &sb);
> +               strbuf_reset(&sb);
> +       } else
> +               t = path;
> +
> +       if (safe_create_leading_directories_const(t) < 0)
> +               die("Could not create directory '%s'", t);
> +
> +       strbuf_addf(&sb, "%s/.git", t);
> +
> +       if (safe_create_leading_directories_const(sb.buf) < 0)
> +               die(_("could not create leading directories of '%s'"), sb.buf);
> +       submodule_dot_git = fopen(sb.buf, "w");
> +       if (!submodule_dot_git)
> +               die ("Cannot open file '%s': %s", sb.buf, strerror(errno)       );
> +
> +       fprintf(submodule_dot_git, "gitdir: %s\n",
> +               relative_path(sm_gitdir, path, &rel_path));
> +       if (fclose(submodule_dot_git))
> +               die("Could not close file %s", sb.buf);
> +       strbuf_reset(&sb);
> +
> +       /* Redirect the worktree of the submodule in the superprojects config */
> +       if (!is_absolute_path(sm_gitdir)) {
> +               char *s = (char*)sm_gitdir;
> +               strbuf_addf(&sb, "%s/%s", xgetcwd(), sm_gitdir);
> +               sm_gitdir = strbuf_detach(&sb, NULL);
> +               strbuf_reset(&sb);
> +               free(s);
> +       }
> +       strbuf_addf(&sb, "%s/%s", xgetcwd(), path);
> +       t = relative_path(sb.buf, sm_gitdir, &rel_path);
> +
> +       p = git_pathdup_submodule(path, "config");
> +       if (!p)
> +               die("Could not get submodule directory for '%s'", path);
> +       git_config_set_in_file(p, "core.worktree", t);
> +       strbuf_release(&sb);
> +       return 0;
> +}
> +
>  int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>  {
>         if (argc < 2)
> @@ -135,6 +286,14 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
>         if (!strcmp(argv[1], "module_name"))
>                 return module_name(argc - 2, argv + 2, prefix);
>
> +       if (!strcmp(argv[1], "module_clone"))
> +               return module_clone(argc - 1, argv + 1, prefix);
> +       if (!strcmp(argv[1], "test")) {
> +               struct strbuf sb = STRBUF_INIT;
> +
> +               relative_path(".git/modules/example", "init", &sb);
> +               return 0;
> +       }
>  usage:
> -       usage("git submodule--helper [module_list module_name]\n");
> +       usage("git submodule--helper [module_list module_name module_clone]\n");
>  }
> diff --git a/git-submodule.sh b/git-submodule.sh
> index e6ff38d..6e8561e 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -178,80 +178,6 @@ get_submodule_config () {
>         printf '%s' "${value:-$default}"
>  }
>
> -#
> -# Clone a submodule
> -#
> -# $1 = submodule path
> -# $2 = submodule name
> -# $3 = URL to clone
> -# $4 = reference repository to reuse (empty for independent)
> -# $5 = depth argument for shallow clones (empty for deep)
> -#
> -# Prior to calling, cmd_update checks that a possibly existing
> -# path is not a git repository.
> -# Likewise, cmd_add checks that path does not exist at all,
> -# since it is the location of a new submodule.
> -#
> -module_clone()
> -{
> -       sm_path=$1
> -       name=$2
> -       url=$3
> -       reference="$4"
> -       depth="$5"
> -       quiet=
> -       if test -n "$GIT_QUIET"
> -       then
> -               quiet=-q
> -       fi
> -
> -       gitdir=
> -       gitdir_base=
> -       base_name=$(dirname "$name")
> -
> -       gitdir=$(git rev-parse --git-dir)
> -       gitdir_base="$gitdir/modules/$base_name"
> -       gitdir="$gitdir/modules/$name"
> -
> -       if test -d "$gitdir"
> -       then
> -               mkdir -p "$sm_path"
> -               rm -f "$gitdir/index"
> -       else
> -               mkdir -p "$gitdir_base"
> -               (
> -                       clear_local_git_env
> -                       git clone $quiet ${depth:+"$depth"} -n ${reference:+"$reference"} \
> -                               --separate-git-dir "$gitdir" "$url" "$sm_path"
> -               ) ||
> -               die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
> -       fi
> -
> -       # We already are at the root of the work tree but cd_to_toplevel will
> -       # resolve any symlinks that might be present in $PWD
> -       a=$(cd_to_toplevel && cd "$gitdir" && pwd)/
> -       b=$(cd_to_toplevel && cd "$sm_path" && pwd)/
> -       # Remove all common leading directories after a sanity check
> -       if test "${a#$b}" != "$a" || test "${b#$a}" != "$b"; then
> -               die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")"
> -       fi
> -       while test "${a%%/*}" = "${b%%/*}"
> -       do
> -               a=${a#*/}
> -               b=${b#*/}
> -       done
> -       # Now chop off the trailing '/'s that were added in the beginning
> -       a=${a%/}
> -       b=${b%/}
> -
> -       # Turn each leading "*/" component into "../"
> -       rel=$(printf '%s\n' "$b" | sed -e 's|[^/][^/]*|..|g')
> -       printf '%s\n' "gitdir: $rel/$a" >"$sm_path/.git"
> -
> -       rel=$(printf '%s\n' "$a" | sed -e 's|[^/][^/]*|..|g')
> -       (clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
> -}
> -
>  isnumber()
>  {
>         n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
> @@ -412,7 +338,7 @@ Use -f if you really want to add it." >&2
>                                 echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
>                         fi
>                 fi
> -               module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" || exit
> +               git submodule--helper module_clone --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" --reference "$reference_path" --depth "$depth" || exit
>                 (
>                         clear_local_git_env
>                         cd "$sm_path" &&
> @@ -774,7 +700,7 @@ Maybe you want to use 'update --init'?")"
>
>                 if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
>                 then
> -                       module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
> +                       git submodule--helper module_clone --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
>                         cloned_modules="$cloned_modules;$name"
>                         subsha1=
>                 else
> --
> 2.5.0.330.g130be8e.dirty
>

^ permalink raw reply	[relevance 7%]

* Re: [PATCH 0/7] Submodule improvements
  2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
                   ` (6 preceding siblings ...)
  2015-08-18  0:22 20% ` [PATCH 7/7] submodule: implement `module_clone` " Stefan Beller
@ 2015-08-18  0:38  7% ` Stefan Beller
  7 siblings, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18  0:38 UTC (permalink / raw)
  To: git@vger.kernel.org
  Cc: Junio C Hamano, Jens Lehmann, Heiko Voigt, Stefan Beller

A last minute change in the last patch broke t7400-submodule-basic.sh, test 82

^ permalink raw reply	[relevance 7%]

* [PATCH 7/7] submodule: implement `module_clone` as a builtin helper
  2015-08-18  0:22 20% ` [PATCH 7/7] submodule: implement `module_clone` " Stefan Beller
  2015-08-18  0:26  7%   ` Stefan Beller
@ 2015-08-18 22:13 20%   ` Stefan Beller
  1 sibling, 0 replies; 200+ results
From: Stefan Beller @ 2015-08-18 22:13 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, hvoigt, Stefan Beller

`module_clone` is part of the update command, which I want to convert
to C next.

Signed-off-by: Stefan Beller <sbeller@google.com>
---

This is the only patch that broke by a last minute fix,
so this replaces the previous PATCH 7/7.

 builtin/submodule--helper.c | 161 +++++++++++++++++++++++++++++++++++++++++++-
 git-submodule.sh            |  80 +---------------------
 2 files changed, 163 insertions(+), 78 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 80d13f5..930aa04 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -8,6 +8,7 @@
 #include "submodule.h"
 #include "submodule-config.h"
 #include "string-list.h"
+#include "run-command.h"
 
 static const struct cache_entry **ce_entries;
 static int ce_alloc, ce_used;
@@ -124,6 +125,156 @@ static int module_name(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static int clone_submodule(const char *path, const char *gitdir, const char *url,
+			   const char *depth, const char *reference, int quiet)
+{
+	struct child_process cp;
+	child_process_init(&cp);
+
+	argv_array_push(&cp.args, "clone");
+	argv_array_push(&cp.args, "--no-checkout");
+	if (quiet)
+		argv_array_push(&cp.args, "--quiet");
+	if (depth && strcmp(depth, "")) {
+		argv_array_push(&cp.args, "--depth");
+		argv_array_push(&cp.args, depth);
+	}
+	if (reference && strcmp(reference, "")) {
+		argv_array_push(&cp.args, "--reference");
+		argv_array_push(&cp.args, reference);
+	}
+	if (gitdir) {
+		argv_array_push(&cp.args, "--separate-git-dir");
+		argv_array_push(&cp.args, gitdir);
+	}
+	argv_array_push(&cp.args, url);
+	argv_array_push(&cp.args, path);
+
+	cp.git_cmd = 1;
+	cp.env = local_repo_env;
+
+	cp.no_stdin = 1;
+	cp.no_stdout = 1;
+	cp.no_stderr = 1;
+
+	return run_command(&cp);
+}
+
+/*
+ * Clone a submodule
+ *
+ * $1 = submodule path
+ * $2 = submodule name
+ * $3 = URL to clone
+ * $4 = reference repository to reuse (empty for independent)
+ * $5 = depth argument for shallow clones (empty for deep)
+ *
+ * Prior to calling, cmd_update checks that a possibly existing
+ * path is not a git repository.
+ * Likewise, cmd_add checks that path does not exist at all,
+ * since it is the location of a new submodule.
+ */
+static int module_clone(int argc, const char **argv, const char *prefix)
+{
+	const char *path = NULL, *name = NULL, *url = NULL, *reference = NULL, *depth = NULL;
+	int quiet = 0;
+	FILE *submodule_dot_git;
+	const char *sm_gitdir, *p;
+	struct strbuf rel_path = STRBUF_INIT;
+	struct strbuf sb = STRBUF_INIT;
+
+	struct option module_update_options[] = {
+		OPT_STRING(0, "prefix", &alternative_path,
+			   N_("path"),
+			   N_("alternative anchor for relative paths")),
+		OPT_STRING(0, "path", &path,
+			   N_("path"),
+			   N_("where the new submodule will be cloned to")),
+		OPT_STRING(0, "name", &name,
+			   N_("string"),
+			   N_("name of the new submodule")),
+		OPT_STRING(0, "url", &url,
+			   N_("string"),
+			   N_("url where to clone the submodule from")),
+		OPT_STRING(0, "reference", &reference,
+			   N_("string"),
+			   N_("reference repository")),
+		OPT_STRING(0, "depth", &depth,
+			   N_("string"),
+			   N_("depth for shallow clones")),
+		OPT_END()
+	};
+
+	static const char * const git_submodule_helper_usage[] = {
+		N_("git submodule--helper update [--prefix=<path>] [--quiet] [--remote] [-N|--no-fetch]"
+		   "[-f|--force] [--rebase|--merge] [--reference <repository>]"
+		   "[--depth <depth>] [--recursive] [--] [<path>...]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, module_update_options,
+			     git_submodule_helper_usage, 0);
+
+	if (getenv("GIT_QUIET"))
+		quiet = 1;
+
+	strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
+	sm_gitdir = strbuf_detach(&sb, NULL);
+	strbuf_reset(&sb);
+
+	if (!file_exists(sm_gitdir)) {
+		safe_create_leading_directories_const(sm_gitdir);
+		if (clone_submodule(path, sm_gitdir, url, depth, reference, quiet))
+			die(N_("Clone of '%s' into submodule path '%s' failed"),
+			    url, path);
+	} else {
+		safe_create_leading_directories_const(path);
+		unlink(sm_gitdir);
+	}
+
+	/* Write a .git file in the submodule to redirect to the superproject. */
+	if (alternative_path && !strcmp(alternative_path, "")) {
+		p = relative_path(path, alternative_path, &sb);
+		strbuf_reset(&sb);
+	} else
+		p = path;
+
+	if (safe_create_leading_directories_const(p) < 0)
+		die("Could not create directory '%s'", p);
+
+	strbuf_addf(&sb, "%s/.git", p);
+
+	if (safe_create_leading_directories_const(sb.buf) < 0)
+		die(_("could not create leading directories of '%s'"), sb.buf);
+	submodule_dot_git = fopen(sb.buf, "w");
+	if (!submodule_dot_git)
+		die ("Cannot open file '%s': %s", sb.buf, strerror(errno));
+
+	fprintf(submodule_dot_git, "gitdir: %s\n",
+		relative_path(sm_gitdir, path, &rel_path));
+	if (fclose(submodule_dot_git))
+		die("Could not close file %s", sb.buf);
+	strbuf_reset(&sb);
+
+	/* Redirect the worktree of the submodule in the superprojects config */
+	if (!is_absolute_path(sm_gitdir)) {
+		char *s = (char*)sm_gitdir;
+		strbuf_addf(&sb, "%s/%s", xgetcwd(), sm_gitdir);
+		sm_gitdir = strbuf_detach(&sb, NULL);
+		strbuf_reset(&sb);
+		free(s);
+	}
+	strbuf_addf(&sb, "%s/%s", xgetcwd(), path);
+
+	p = git_pathdup_submodule(path, "config");
+	if (!p)
+		die("Could not get submodule directory for '%s'", path);
+	git_config_set_in_file(p, "core.worktree",
+			       relative_path(sb.buf, sm_gitdir, &rel_path));
+	strbuf_release(&sb);
+	return 0;
+}
+
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 {
 	if (argc < 2)
@@ -135,6 +286,14 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
 	if (!strcmp(argv[1], "module_name"))
 		return module_name(argc - 2, argv + 2, prefix);
 
+	if (!strcmp(argv[1], "module_clone"))
+		return module_clone(argc - 1, argv + 1, prefix);
+	if (!strcmp(argv[1], "test")) {
+		struct strbuf sb = STRBUF_INIT;
+
+		relative_path(".git/modules/example", "init", &sb);
+		return 0;
+	}
 usage:
-	usage("git submodule--helper [module_list module_name]\n");
+	usage("git submodule--helper [module_list module_name module_clone]\n");
 }
diff --git a/git-submodule.sh b/git-submodule.sh
index e6ff38d..e50451b 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -178,80 +178,6 @@ get_submodule_config () {
 	printf '%s' "${value:-$default}"
 }
 
-#
-# Clone a submodule
-#
-# $1 = submodule path
-# $2 = submodule name
-# $3 = URL to clone
-# $4 = reference repository to reuse (empty for independent)
-# $5 = depth argument for shallow clones (empty for deep)
-#
-# Prior to calling, cmd_update checks that a possibly existing
-# path is not a git repository.
-# Likewise, cmd_add checks that path does not exist at all,
-# since it is the location of a new submodule.
-#
-module_clone()
-{
-	sm_path=$1
-	name=$2
-	url=$3
-	reference="$4"
-	depth="$5"
-	quiet=
-	if test -n "$GIT_QUIET"
-	then
-		quiet=-q
-	fi
-
-	gitdir=
-	gitdir_base=
-	base_name=$(dirname "$name")
-
-	gitdir=$(git rev-parse --git-dir)
-	gitdir_base="$gitdir/modules/$base_name"
-	gitdir="$gitdir/modules/$name"
-
-	if test -d "$gitdir"
-	then
-		mkdir -p "$sm_path"
-		rm -f "$gitdir/index"
-	else
-		mkdir -p "$gitdir_base"
-		(
-			clear_local_git_env
-			git clone $quiet ${depth:+"$depth"} -n ${reference:+"$reference"} \
-				--separate-git-dir "$gitdir" "$url" "$sm_path"
-		) ||
-		die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
-	fi
-
-	# We already are at the root of the work tree but cd_to_toplevel will
-	# resolve any symlinks that might be present in $PWD
-	a=$(cd_to_toplevel && cd "$gitdir" && pwd)/
-	b=$(cd_to_toplevel && cd "$sm_path" && pwd)/
-	# Remove all common leading directories after a sanity check
-	if test "${a#$b}" != "$a" || test "${b#$a}" != "$b"; then
-		die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")"
-	fi
-	while test "${a%%/*}" = "${b%%/*}"
-	do
-		a=${a#*/}
-		b=${b#*/}
-	done
-	# Now chop off the trailing '/'s that were added in the beginning
-	a=${a%/}
-	b=${b%/}
-
-	# Turn each leading "*/" component into "../"
-	rel=$(printf '%s\n' "$b" | sed -e 's|[^/][^/]*|..|g')
-	printf '%s\n' "gitdir: $rel/$a" >"$sm_path/.git"
-
-	rel=$(printf '%s\n' "$a" | sed -e 's|[^/][^/]*|..|g')
-	(clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
-}
-
 isnumber()
 {
 	n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
@@ -301,7 +227,7 @@ cmd_add()
 			shift
 			;;
 		--depth=*)
-			depth=$1
+			depth="$1"
 			;;
 		--)
 			shift
@@ -412,7 +338,7 @@ Use -f if you really want to add it." >&2
 				echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
 			fi
 		fi
-		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" || exit
+		git submodule--helper module_clone --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" --reference "$reference_path" --depth "$depth" || exit
 		(
 			clear_local_git_env
 			cd "$sm_path" &&
@@ -774,7 +700,7 @@ Maybe you want to use 'update --init'?")"
 
 		if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
 		then
-			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
+			git submodule--helper module_clone --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
 			cloned_modules="$cloned_modules;$name"
 			subsha1=
 		else
-- 
2.5.0.342.g44e0223

^ permalink raw reply related	[relevance 20%]

* Re: [PATCH 4/7] submodule: Allow errornous values for the fetchrecursesubmodules option
  2015-08-18  0:22 26% ` [PATCH 4/7] submodule: Allow errornous values for the fetchrecursesubmodules option Stefan Beller
@ 2015-08-19 18:09  4%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2015-08-19 18:09 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, Jens.Lehmann, hvoigt

Stefan Beller <sbeller@google.com> writes:

> From: Heiko Voigt <hvoigt@hvoigt.net>
>
> We should not die when reading the submodule config cache since the user
> might not be able to get out of that situation when the configuration is
> part of the history.
>
> We should handle this condition later when the value is about to be
> used.
>
> Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---

The retitle is good but we'd need to typofix erroneous there, I
think (will do so while queuing, no need to resend).

^ permalink raw reply	[relevance 4%]

Results 1-200 of ~6000   | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2012-09-18 11:23  3% git installation fails in home directory on ubuntu 12.04 Stefan Beller
2013-07-19 14:08  5% [PATCH] status_printf_ln: Suppress false positive warnings of empty format string Stefan Beller
2013-07-19 16:01  2% ` Junio C Hamano
2013-07-29 19:49     [PATCH 0/4] Removing deprecated parsing macros Stefan Beller
2013-07-29 19:49  5% ` [PATCH 1/4] Replace deprecated OPT_BOOLEAN by OPT_BOOL Stefan Beller
2013-07-30 18:00     [PATCH] tag: Use OPT_BOOL instead of OPT_BOOLEAN to allow one action multiple times Stefan Beller
2013-07-30 19:24     ` Junio C Hamano
2013-07-30 21:28       ` Stefan Beller
2013-07-30 22:28         ` Junio C Hamano
2013-07-31 10:34           ` Stefan Beller
2013-07-31 23:10  5%         ` Junio C Hamano
2013-08-17 15:01  4%           ` Stefano Lattarini
2013-07-31 16:28     [PATCHv2 0/9] Removing deprecated parsing macros Stefan Beller
2013-07-31 16:28  3% ` [PATCHv2 2/9] Replace deprecated OPT_BOOLEAN by OPT_BOOL Stefan Beller
2013-08-01 21:14  2% [ANNOUNCE] Git v1.8.4-rc1 Junio C Hamano
2013-08-02 13:48     Rewriting git-repack.sh in C Stefan Beller
2013-08-02 14:10     ` Duy Nguyen
2013-08-02 16:36  1%   ` Duy Nguyen
2013-08-03 10:03     Duy Nguyen
2013-08-07 14:00     ` [PATCH 0/4] " Stefan Beller
2013-08-07 14:00  1%   ` [PATCH 1/4] Build in git-repack Stefan Beller
2013-08-03 11:51     [PATCHv3 0/9] Removing deprecated parsing macros Stefan Beller
2013-08-03 11:51  3% ` [PATCHv3 2/9] Replace deprecated OPT_BOOLEAN by OPT_BOOL Stefan Beller
2013-08-08 18:31     [PATCH] diff: remove ternary operator evaluating always to true Stefan Beller
2013-08-10  7:21     ` Jeff King
2013-08-12  5:46  2%   ` Junio C Hamano
2013-08-12  8:32  5%     ` Stefan Beller
2013-08-12 17:15  2%       ` Junio C Hamano
2013-08-08 18:55  6% [PATCH] diff: remove another ternary expression always evaluating " Stefan Beller
2013-08-08 21:01  2% ` Johannes Schindelin
2013-08-08 21:22  6%   ` Stefan Beller
2013-08-08 21:36  4%     ` Johannes Schindelin
2013-08-08 22:03  0%       ` Junio C Hamano
2013-08-08 21:36  2% ` Philip Oakley
2013-08-08 23:02  2% [ANNOUNCE] Git v1.8.4-rc2 Junio C Hamano
2013-08-13 19:23     [PATCH] Rewriting git-repack in C Stefan Beller
2013-08-13 19:23  4% ` [PATCH] repack: rewrite the shell script " Stefan Beller
2013-08-13 22:09  2% [ANNOUNCE] Git v1.8.4-rc3 Junio C Hamano
2013-08-14 16:26     [PATCH] repack: rewrite the shell script in C Stefan Beller
2013-08-14 16:27  3% ` [RFC PATCH] " Stefan Beller
2013-08-15 17:15     Junio C Hamano
2013-08-16  0:12  6% ` [RFC PATCHv2] " Stefan Beller
2013-08-17 13:34  0%   ` René Scharfe
2013-08-18 14:34     Stefan Beller
2013-08-18 14:36  6% ` [RFC PATCHv3] " Stefan Beller
2013-08-18 16:44     René Scharfe
2013-08-18 22:26  6% ` [RFC PATCHv4] " Stefan Beller
2013-08-19 23:23  6%   ` Stefan Beller
2013-08-20 13:31         ` Johannes Sixt
2013-08-20 21:24           ` Stefan Beller
2013-08-20 21:34             ` Jonathan Nieder
2013-08-20 21:40               ` Dokumenting api-paths.txt Stefan Beller
2013-08-20 21:59                 ` Jonathan Nieder
2013-08-21 22:43                   ` Stefan Beller
2013-08-22 17:29  4%                 ` Junio C Hamano
2013-08-20 22:36     [RFC PATCHv4] repack: rewrite the shell script in C Stefan Beller
2013-08-20 22:38  6% ` [PATCH] " Stefan Beller
2013-08-21 17:25     Stefan Beller
2013-08-21 17:28  6% ` [RFC PATCHv6 1/2] " Stefan Beller
2013-08-29 20:39     [PATCHv7 0/2] Rewriting repack " Stefan Beller
2013-08-29 20:39  3% ` [PATCH 1/2] repack: rewrite the shell script " Stefan Beller
2013-09-15 11:42  2%   ` René Scharfe
2013-09-15 15:33  2% [PATCH 1/3] " Stefan Beller
2013-10-26 17:03 12% [PATCH 1/2] refs: remove unused function invalidate_ref_cache Stefan Beller
2013-10-31 23:03     [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line Stefan Beller
2013-10-31 23:04  5% ` [PATCH] Documentation: add a script to generate a (long/short) options overview Stefan Beller
2013-10-31 23:09  7%   ` Stefan Beller
2013-11-06 23:57  2% [ANNOUNCE] Git v1.8.5-rc1 Junio C Hamano
2014-07-23 13:35  4% Unify subcommand structure; introduce double dashes for all subcommands? Stefan Beller
2014-07-23 17:52  2% ` Junio C Hamano
2014-08-10 15:26  2%   ` Stefan Beller
2014-07-27 23:18  3% [ANNOUNCE] Git v2.1.0-rc0 Junio C Hamano
2014-08-08 22:17  2% [ANNOUNCE] Git v2.1.0-rc2 Junio C Hamano
2014-10-24 22:34  2% What's cooking in git.git (Oct 2014, #06; Fri, 24) Junio C Hamano
2014-11-26 23:09  3% What's cooking in git.git (Nov 2014, #04; Wed, 26) Junio C Hamano
2014-12-03 21:07  3% What's cooking in git.git (Dec 2014, #01; Wed, 3) Junio C Hamano
2014-12-10 22:38  3% What's cooking in git.git (Dec 2014, #02; Wed, 10) Junio C Hamano
2014-12-15 20:40  2% What's cooking in git.git (Dec 2014, #03; Mon, 15) Junio C Hamano
2014-12-22 23:17  2% What's cooking in git.git (Dec 2014, #04; Mon, 22) Junio C Hamano
2014-12-29 21:28  3% What's cooking in git.git (Dec 2014, #05; Mon, 29) Junio C Hamano
2015-01-12 23:57  1% [ANNOUNCE] Git v2.3.0-rc0 Junio C Hamano
2015-03-06 23:11  3% [ANNOUNCE] Git v2.3.2 Junio C Hamano
2015-04-02 22:08  2% [ANNOUNCE] Git v2.4.0-rc1 Junio C Hamano
2015-04-14 21:48  2% [ANNOUNCE] Git v2.4.0-rc2 Junio C Hamano
2015-04-16  2:05  3% ` Bryan Turner
2015-04-22 23:24     [PATCH v2 00/16] Convert parts of refs.c to struct object_id brian m. carlson
2015-04-22 23:24     ` [PATCH v2 02/16] refs: convert for_each_tag_ref " brian m. carlson
2015-04-23 18:13  2%   ` Stefan Beller
2015-04-23 19:27  4%     ` Jeff King
2015-04-26  4:29     [PATCH v4 2/5] setup: sanity check file size in read_gitfile_gently Junio C Hamano
2015-04-26  6:49     ` [PATCH v5 0/5] Improving performance of git clean Erik Elfström
2015-04-26  6:49       ` [PATCH v5 1/5] setup: add gentle version of read_gitfile Erik Elfström
2015-04-29 23:47  2%     ` Stefan Beller
2015-04-29 20:53     Diffing submodule does not yield complete logs for merge commits Robert Dailey
2015-05-01 17:57     ` Heiko Voigt
2015-05-04 15:05       ` Robert Dailey
2015-05-04 19:32         ` Jens Lehmann
2015-05-04 20:21           ` Robert Dailey
2015-05-05  5:49             ` Johannes Schindelin
2015-05-15 20:33               ` Robert Dailey
2015-05-18 12:30                 ` Heiko Voigt
2015-05-18 15:06                   ` Robert Dailey
2015-05-19 10:44                     ` Heiko Voigt
2015-05-19 19:29                       ` Robert Dailey
2015-05-19 20:34  4%                     ` Stefan Beller
2015-05-22  9:17  4%                       ` Roberto Tyley
2015-04-30 19:51  2% [ANNOUNCE] Git v2.4.0 Junio C Hamano
2015-05-01 11:01     Patch that modifies git usage message Alangi Derick
2015-05-01 15:51     ` Stefan Beller
2015-05-01 16:29       ` Junio C Hamano
2015-05-01 16:55  4%     ` Stefan Beller
2015-05-03 22:19     [PATCH] fixed translation errors Alangi Derick
2015-05-04 17:39  2% ` Stefan Beller
2015-05-18 13:39     [PATCH v2] pull: handle --log=<n> Paul Tan
2015-05-18 14:53     ` Johannes Schindelin
2015-05-18 18:18       ` Junio C Hamano
2015-05-19 13:35         ` Johannes Schindelin
2015-05-19 13:57           ` Junio C Hamano
2015-05-19 21:24             ` Dennis Kaarsemaker
2015-05-19 21:33               ` Stefan Beller
2015-05-19 21:43  3%             ` Dennis Kaarsemaker
2015-05-18 15:05     [PATCH 00/14] Make git-pull a builtin Paul Tan
2015-05-18 15:06     ` [PATCH 11/14] pull: teach git pull about --rebase Paul Tan
2015-05-18 23:36  2%   ` Stefan Beller
2015-05-20 16:17     corrupt repos does not return error with `git fsck` Faheem Mitha
2015-05-20 17:19     ` [PUB]corrupt " Matthieu Moy
2015-05-20 17:40       ` Johannes Schindelin
2015-05-20 18:02         ` Stefan Beller
2015-05-20 18:19  4%       ` John Keeping
2015-05-20 23:11 21% [PATCH] submodule documentation: Reorder introductory paragraphs Stefan Beller
2015-05-21 13:04  4% ` Heiko Voigt
2015-05-21 17:24  6% ` Junio C Hamano
2015-05-21 17:43  7%   ` Stefan Beller
2015-05-21 20:03  4% ` Philip Oakley
2015-05-21 22:08  7%   ` Stefan Beller
2015-05-22  6:59  4%     ` Philip Oakley
2015-05-22 14:36  4%     ` Junio C Hamano
2015-05-22 17:05  4%       ` Stefan Beller
2015-05-22 17:26  4%         ` Junio C Hamano
2015-05-22 17:35  7%         ` Philip Oakley
2015-05-22 17:51  4%           ` Stefan Beller
2015-05-22 19:47  4%             ` Philip Oakley
2015-05-21 19:01 23% [PATCH] submodule documentation: Rewrite " Stefan Beller
2015-05-22  8:33  3% [Announce] submitGit for patch submission (was "Diffing submodule does not yield complete logs") Roberto Tyley
2015-05-22  9:42  2% ` Johannes Schindelin
2015-05-22 14:41  2%   ` Johannes Schindelin
2015-05-22 17:14  2%     ` Philip Oakley
2015-05-22 19:58  2%       ` Johannes Schindelin
2015-05-22 21:35  2%         ` Philip Oakley
2015-05-22 14:17     ` Junio C Hamano
2015-05-22 17:40       ` Philip Oakley
2015-05-22 19:23  4%     ` Stefan Beller
2015-05-22 19:59  4%       ` Johannes Schindelin
2015-05-22 20:04  2%         ` Junio C Hamano
2015-05-22 20:44  4%           ` Stefan Beller
2015-05-23  9:11  2%           ` Johannes Schindelin
2015-05-23 14:29  4%       ` Matthieu Moy
2015-05-22 16:53  4% ` Stefan Beller
2015-05-22 19:38 23% [PATCH] submodule documentation: Reorder introductory paragraphs Stefan Beller
2015-05-22 21:18  4% ` Philip Oakley
2015-05-25 22:00  6% ` Junio C Hamano
2015-05-26 17:53  7%   ` Stefan Beller
2015-05-26 21:58  7%     ` Heiko Voigt
2015-05-26 21:47     What's cooking in git.git (May 2015, #07; Tue, 26) Junio C Hamano
2015-05-26 22:06  2% ` Stefan Beller
2015-05-27 19:48 23% [PATCHv3] submodule documentation: Reorder introductory paragraphs Stefan Beller
2015-05-27 21:13  9% [PATCH] glossary: add "remote" and "submodule" Stefan Beller
2015-05-27 22:29  7% ` Junio C Hamano
2015-05-27 22:59  7%   ` Stefan Beller
2015-05-27 23:05  7%     ` Junio C Hamano
2015-05-27 23:29  8%       ` Stefan Beller
2015-05-28  1:50 10%         ` [PATCH] glossary: add "remote", "submodule", "superproject" Stefan Beller
2015-05-28 16:45  7%           ` Junio C Hamano
2015-05-28 17:52  7%             ` Stefan Beller
2015-05-28 18:50  4%               ` Junio C Hamano
2015-05-29 18:23 12% Stefan Beller
2015-06-03  6:48     [PATCH v2 00/19] Make git-pull a builtin Paul Tan
2015-06-03  6:48     ` [PATCH v2 08/19] pull: pass git-fetch's options to git-fetch Paul Tan
2015-06-03 17:16  2%   ` Stefan Beller
2015-06-06 17:49     Submodules as first class citizens (was Re: Moving to subtrees for plugins?) Phil Hord
2015-06-06 19:53     ` Luca Milanesio
2015-06-07  6:26  4%   ` Stefan Beller
2015-06-09 18:40  7%     ` Jens Lehmann
2015-06-11 16:11  4%       ` Phil Hord
2015-06-11 18:56  5%         ` Jens Lehmann
2015-06-15  9:03  2%       ` Heiko Voigt
2015-06-15 21:06     [PATCH v5 0/4] submodule config lookup API Heiko Voigt
2015-06-15 21:48     ` Junio C Hamano
2015-08-10 19:23  7%   ` Stefan Beller
2015-08-12 17:53  4%     ` Junio C Hamano
2015-06-16 22:15  4% [ANNOUNCE] Git v2.4.4 Junio C Hamano
2015-06-23  0:50     RFC/Pull Request: Refs db backend David Turner
2015-06-23 17:16  2% ` Stefan Beller
     [not found]     <45DF444C03B59343B5893402DC4F867E3A800EC7@PB2OAEXM01.oad.exch.int>
2015-06-23  8:52     ` Dependency Management Jean Audibert
2015-06-23 17:34  4%   ` Stefan Beller
2015-06-23 18:49  4%     ` Josh Hagins
2015-06-25  9:00  0%       ` Luke Diamand
2015-06-25 20:19  1% [ANNOUNCE] Git v2.5.0-rc0 Junio C Hamano
2015-07-13 21:52  1% [ANNOUNCE] Git v2.5.0-rc2 Junio C Hamano
2015-07-21 22:08  1% [ANNOUNCE] Git v2.5.0-rc3 Junio C Hamano
2015-07-27 20:47  1% [ANNOUNCE] Git v2.5.0 Junio C Hamano
2015-07-31  0:19  7% [PATCH] add: remove dead code Stefan Beller
2015-07-31 16:41  5% ` Junio C Hamano
2015-07-31 23:09 10% ` [RFC/PATCH 0/2] Submodules: refactoring the `module_list` function Stefan Beller
2015-07-31 23:09 14% ` [RFC/PATCH 1/2] submodule: implement `module_list` as a builtin helper Stefan Beller
2015-08-01  1:01  7%   ` Junio C Hamano
2015-08-03 21:30  7%     ` Stefan Beller
2015-08-03 21:38  6%       ` Junio C Hamano
2015-08-03 21:58 18%       ` [PATCH] " Stefan Beller
2015-08-03 22:04  6%       ` [RFC/PATCH 1/2] " Junio C Hamano
2015-08-03 22:13  4%         ` Stefan Beller
2015-08-03 22:58 19%         ` [PATCH] " Stefan Beller
2015-07-31 23:09 17% ` [RFC/PATCH 2/2] Testing the new code Stefan Beller
2015-08-01  1:02  2%   ` Junio C Hamano
2015-08-03 16:23  2%     ` Stefan Beller
2015-08-03 19:47  2%       ` Junio C Hamano
2015-08-03 17:53  5% [PATCH] builtin/mv: Get rid of the last caller of get_pathspec Stefan Beller
2015-08-03 22:48     Eric Sunshine
2015-08-06 18:27     ` [PATCH 0/2] Remove get_pathspec finally Stefan Beller
2015-08-06 18:27  7%   ` [PATCH 1/2] builtin/mv: remove get_pathspec() Stefan Beller
2015-08-06 18:46  2%     ` Eric Sunshine
2015-08-06 18:58  2%       ` Stefan Beller
2015-08-04 21:51     [PATCH v6 0/2] path: implement common_dir handling in git_path_submodule() Max Kirillov
2015-08-04 22:05     ` [PATCH v7 " Max Kirillov
2015-08-04 22:05       ` [PATCH v7 1/2] submodule refactor: use git_path_submodule() in add_submodule_odb() Max Kirillov
2015-08-18  0:07  7%     ` Stefan Beller
2015-08-04 22:05       ` [PATCH v7 2/2] path: implement common_dir handling in git_path_submodule() Max Kirillov
2015-08-17 23:56  2%     ` Stefan Beller
2015-08-05  0:04 19% [PATCH 1/4] submodule: implement `module_list` as a builtin helper Stefan Beller
2015-08-05  0:04 23% ` [PATCH 2/4] submodule: implement `module_name` " Stefan Beller
2015-08-05  0:05  4%   ` Stefan Beller
2015-08-05  0:58  4%   ` Eric Sunshine
2015-08-05 16:29  4%     ` Stefan Beller
2015-08-05 19:06  7%   ` Jens Lehmann
2015-08-05 19:55  7%     ` Stefan Beller
2015-08-05 21:08 23%       ` [PATCH] " Stefan Beller
2015-08-06 19:49  6%         ` Jens Lehmann
2015-08-06 21:38 24%           ` Stefan Beller
2015-08-07 20:03  7%             ` Junio C Hamano
2015-08-07 20:54  4%               ` Stefan Beller
2015-08-07 20:17               ` Junio C Hamano
2015-08-07 20:49  7%             ` Stefan Beller
2015-08-07 21:14  6%               ` Junio C Hamano
2015-08-07 21:21  7%                 ` Stefan Beller
2015-08-07 21:32  4%                   ` Junio C Hamano
2015-08-07 22:04  7%                     ` Stefan Beller
2015-08-07 22:18  4%                       ` Junio C Hamano
2015-08-07 23:12  4%                         ` Stefan Beller
2015-08-07 22:42  7%                   ` Junio C Hamano
2015-08-07 23:19  7%                     ` Stefan Beller
2015-08-08  0:21  4%                       ` Junio C Hamano
2015-08-08  6:20                             ` Junio C Hamano
2015-08-10 17:03  7%                           ` Stefan Beller
2015-08-05 18:31  6% ` [PATCH 1/4] submodule: implement `module_list` " Jens Lehmann
2015-08-07 19:53  4% ` Junio C Hamano
2015-08-06 17:35  9% [RFC/PATCH 0/4] parallel fetch for submodules Stefan Beller
2015-08-06 17:35 24% ` [PATCH 1/4] submodule: implement `module_name` as a builtin helper Stefan Beller
2015-08-06 19:49  7%   ` Jens Lehmann
2015-08-06 17:35 21% ` [RFC PATCH 4/4] submodule: add infrastructure to fetch submodules in parallel Stefan Beller
2015-08-06 20:08  4% ` [RFC/PATCH 0/4] parallel fetch for submodules Jens Lehmann
2015-08-06 20:44  6%   ` Stefan Beller
2015-08-12 19:13 10% [PATCH v5 0/4] submodule config lookup API Stefan Beller
2015-08-12 19:13 20% ` [PATCH 1/2] Fixup hv/documentation Stefan Beller
2015-08-12 19:13 22% ` [PATCH 2/2] cleanup submodule_config a bit Stefan Beller
2015-08-12 21:13  4%   ` Eric Sunshine
2015-08-12 21:34  4%     ` Stefan Beller
2015-08-12 22:01  2%       ` Eric Sunshine
2015-08-12 19:27  4% ` [PATCH v5 0/4] submodule config lookup API Junio C Hamano
2015-08-17 22:34     What's cooking in git.git (Aug 2015, #03; Mon, 17) Junio C Hamano
2015-08-17 23:28  4% ` Stefan Beller
2015-08-18  0:21  9% [PATCH 0/7] Submodule improvements Stefan Beller
2015-08-18  0:21 14% ` [PATCH 1/7] submodule: implement a config API for lookup of .gitmodules values Stefan Beller
2015-08-18  0:21 11% ` [PATCH 2/7] submodule: extract functions for config set and lookup Stefan Beller
2015-08-18  0:21 23% ` [PATCH 3/7] submodule: use new config API for worktree configurations Stefan Beller
2015-08-18  0:22 26% ` [PATCH 4/7] submodule: Allow errornous values for the fetchrecursesubmodules option Stefan Beller
2015-08-19 18:09  4%   ` Junio C Hamano
2015-08-18  0:22 19% ` [PATCH 5/7] submodule: implement `module_list` as a builtin helper Stefan Beller
2015-08-18  0:22 24% ` [PATCH 6/7] submodule: implement `module_name` " Stefan Beller
2015-08-18  0:22 20% ` [PATCH 7/7] submodule: implement `module_clone` " Stefan Beller
2015-08-18  0:26  7%   ` Stefan Beller
2015-08-18 22:13 20%   ` Stefan Beller
2015-08-18  0:38  7% ` [PATCH 0/7] Submodule improvements Stefan Beller

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).