Git development
 help / color / mirror / Atom feed
* Re: [PATCH v7 4/6] stash: teach 'push' (and 'create_stash') to honor pathspec
From: Junio C Hamano @ 2017-02-27 22:58 UTC (permalink / raw)
  To: Thomas Gummerer
  Cc: git, Jeff King, Johannes Schindelin, sunny, Jakub Narębski,
	Matthieu Moy
In-Reply-To: <20170227215627.GB17065@hank>

Thomas Gummerer <t.gummerer@gmail.com> writes:

> On 02/27, Junio C Hamano wrote:
>> Thomas Gummerer <t.gummerer@gmail.com> writes:
>> 
>> > +	test -n "$untracked" || git ls-files --error-unmatch -- "$@" >/dev/null || exit 1
>> 
>> This silent "exit 1" made me scratch my head, but --error-unmatch
>> would have already given an error message, like
>> 
>>     error: pathspec 'no such' did not match any file(s) known to git.
>>     Did you forget to 'git add'?
>> 
>> so that would be OK.
>
> Yeah exactly, the plan was to let --error-unmatch print the error
> message, as it's better at giving a good error message than we could
> easily do here I think.
>
> Maybe this deserves a comment so others won't have the same doubts
> about this line?

Nah, I do not think so.  It probably is obvious for those who write
(and read) "--error-unmatch".  I was just being slow to realize that
the sole point of that option was to complain ;-)

^ permalink raw reply

* Re: [PATCH] t6300: avoid creating refs/heads/HEAD
From: Jeff King @ 2017-02-27 21:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqqefyjnwat.fsf@gitster.mtv.corp.google.com>

On Mon, Feb 27, 2017 at 01:44:26PM -0800, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
> 
> > ...  I suspect that calling interpret_empty_at() from
> > that function is fundamentally flawed.  The "@" end user types never
> > means refs/heads/HEAD, and HEAD@{either reflog or -1} would not mean
> > anything that should be taken as a branch_name, either.  
> 
> The latter should read "HEAD@{either reflog or -1 or 'upstream'}"
> 
> Or do we make HEAD@{upstream} to mean "deref HEAD to learn the
> current branch name and then take its upstream"?  If so @@{upstream}
> might logically make sense, but I do not see why @{upstream} without
> HEAD or @ is not sufficient to begin with, so...

Yes, HEAD@{upstream} and @@{upstream} are both resolved to the actual
branch name. I also was puzzled whether there was any real use over just
@{upstream}. But it does work, and if you had a script which looked for,
say, $branch@{upstream}, you'd probably want branch=HEAD to keep
working.

The "branch=@" case I am less sympathetic to, as it was mainly supposed
to be a command-line convenience. But it _does_ work now.

-Peff

^ permalink raw reply

* Re: [PATCH v7 4/6] stash: teach 'push' (and 'create_stash') to honor pathspec
From: Junio C Hamano @ 2017-02-27 21:09 UTC (permalink / raw)
  To: Thomas Gummerer
  Cc: git, Jeff King, Johannes Schindelin, sunny, Jakub Narębski,
	Matthieu Moy
In-Reply-To: <20170225213306.2410-5-t.gummerer@gmail.com>

Thomas Gummerer <t.gummerer@gmail.com> writes:

>  	if test -z "$patch_mode"
>  	then
> -		git reset --hard ${GIT_QUIET:+-q}
> +		if test $# != 0
> +		then
> +			git reset ${GIT_QUIET:+-q} -- "$@"
> +			git checkout ${GIT_QUIET:+-q} HEAD -- $(git ls-files -z --modified "$@")

"ls-files -z" on the command line?  

Apparently new tests do not cover the correctness of this codepath.

I wonder if this

	git ls-files -z --modified "$@" |
	git checkout-index -z --force --stdin

is what the above "checkout" wanted to do.  The "reset" in the
previous step presumably updated the index entries that match
specified pathspec to those of the HEAD, so checking out the paths
that match "$@" from the index would be the same as checking them
out from the HEAD (while updating the index with them).

Perhaps squash the following into an appropriate patch in the
series?

 git-stash.sh     |  3 ++-
 t/t3903-stash.sh | 16 ++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/git-stash.sh b/git-stash.sh
index 28d0624c75..9c70662cc8 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -300,7 +300,8 @@ push_stash () {
 		if test $# != 0
 		then
 			git reset ${GIT_QUIET:+-q} -- "$@"
-			git checkout ${GIT_QUIET:+-q} HEAD -- $(git ls-files -z --modified "$@")
+			git ls-files -z --modified -- "$@" |
+			git checkout-index -z --force --stdin
 			git clean --force ${GIT_QUIET:+-q} -d -- "$@"
 		else
 			git reset --hard ${GIT_QUIET:+-q}
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index f7733b4dd4..e868aafab2 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -891,4 +891,20 @@ test_expect_success 'stash without verb with pathspec' '
 	test_path_is_file bar
 '
 
+test_expect_success 'stash with pathspec matching multiple paths' '
+	echo original >file &&
+	echo original >other-file &&
+	git commit -m "two" file other-file &&
+	echo modified >file &&
+	echo modified >other-file &&
+	git stash -- "*file" &&
+	echo original >expect &&
+	test_cmp expect file &&
+	test_cmp expect other-file &&
+	git stash pop &&
+	echo modified >expect &&
+	test_cmp expect file &&
+	test_cmp expect other-file
+'
+
 test_done

^ permalink raw reply related

* [PATCH 6/6] Use time_t where appropriate
From: Johannes Schindelin @ 2017-02-27 21:31 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano
In-Reply-To: <cover.1488231002.git.johannes.schindelin@gmx.de>

Git's source code assumes that unsigned long is at least as precise as
time_t. That causes a lot of problems, in particular where unsigned long
is only 32-bit (notably on Windows, even in 64-bit versions).

So let's just use time_t instead.

Note that in some systems (most notably 32-bit Linux), time_t is *still*
only 32-bit.

Therefore, it might seem desirable to simply replace unsigned long by
int64_t when working with timestamps, but that comes with its own set of
problems, as we often interact with the system's date functions that
*do* use time_t.

So let's just stick with time_t.

By necessity, this is a very, very large patch, as it has to replace all
timestamps' data type in one go.

As `time_t` can be signed, we now have to switch to using LONG_MAX as
the maximum timestamp lest expressions like `timestamp < TIME_MAX`
evaluate to false. Technically, this introduces a limitation on
platforms where we used 64-bit unsigned longs to represent timestamps
before. Practically, however, this simply unifies the behavior with
platforms where `time_t` is signed (and where sending too large
timestamps to libc functions would fail).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/technical/api-parse-options.txt |  8 ++---
 builtin/am.c                                  |  2 +-
 builtin/blame.c                               |  8 ++---
 builtin/fsck.c                                |  4 +--
 builtin/gc.c                                  |  2 +-
 builtin/log.c                                 |  2 +-
 builtin/merge-base.c                          |  2 +-
 builtin/name-rev.c                            |  6 ++--
 builtin/pack-objects.c                        |  4 +--
 builtin/prune.c                               |  2 +-
 builtin/receive-pack.c                        |  6 ++--
 builtin/reflog.c                              | 24 ++++++-------
 builtin/show-branch.c                         |  4 +--
 builtin/worktree.c                            |  2 +-
 bundle.c                                      |  2 +-
 cache.h                                       | 14 ++++----
 commit.c                                      | 12 +++----
 commit.h                                      |  2 +-
 config.mak.uname                              |  2 ++
 credential-cache--daemon.c                    | 12 +++----
 date.c                                        | 50 +++++++++++++--------------
 fetch-pack.c                                  |  6 ++--
 git-compat-util.h                             |  2 +-
 http-backend.c                                |  4 +--
 parse-options-cb.c                            |  4 +--
 pretty.c                                      |  2 +-
 reachable.c                                   | 10 +++---
 reachable.h                                   |  4 +--
 ref-filter.c                                  |  2 +-
 reflog-walk.c                                 |  8 ++---
 refs.c                                        | 14 ++++----
 refs.h                                        |  8 ++---
 refs/files-backend.c                          |  4 +--
 revision.c                                    |  6 ++--
 revision.h                                    |  4 +--
 sha1_name.c                                   |  6 ++--
 t/helper/test-date.c                          |  4 +--
 t/helper/test-parse-options.c                 |  2 +-
 tag.c                                         |  2 +-
 tag.h                                         |  2 +-
 upload-pack.c                                 |  4 +--
 vcs-svn/fast_export.c                         |  4 +--
 vcs-svn/fast_export.h                         |  4 +--
 vcs-svn/svndump.c                             |  2 +-
 wt-status.c                                   |  2 +-
 45 files changed, 140 insertions(+), 140 deletions(-)

diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index 27bd701c0d6..28c9a64fc11 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -178,13 +178,13 @@ There are some macros to easily define options:
 	scale the provided value by 1024, 1024^2 or 1024^3 respectively.
 	The scaled value is put into `unsigned_long_var`.
 
-`OPT_DATE(short, long, &int_var, description)`::
+`OPT_DATE(short, long, &time_t_var, description)`::
 	Introduce an option with date argument, see `approxidate()`.
-	The timestamp is put into `int_var`.
+	The timestamp is put into `time_t_var`.
 
-`OPT_EXPIRY_DATE(short, long, &int_var, description)`::
+`OPT_EXPIRY_DATE(short, long, &time_t_var, description)`::
 	Introduce an option with expiry date argument, see `parse_expiry_date()`.
-	The timestamp is put into `int_var`.
+	The timestamp is put into `time_t_var`.
 
 `OPT_CALLBACK(short, long, &var, arg_str, description, func_ptr)`::
 	Introduce an option with argument.
diff --git a/builtin/am.c b/builtin/am.c
index 75e2d939036..c3e0a4816e4 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -877,7 +877,7 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
 		if (skip_prefix(sb.buf, "# User ", &str))
 			fprintf(out, "From: %s\n", str);
 		else if (skip_prefix(sb.buf, "# Date ", &str)) {
-			unsigned long timestamp;
+			time_t timestamp;
 			long tz, tz2;
 			char *end;
 
diff --git a/builtin/blame.c b/builtin/blame.c
index c9486dd580b..33701a1353e 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1570,13 +1570,13 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 struct commit_info {
 	struct strbuf author;
 	struct strbuf author_mail;
-	unsigned long author_time;
+	time_t author_time;
 	struct strbuf author_tz;
 
 	/* filled only when asked for details */
 	struct strbuf committer;
 	struct strbuf committer_mail;
-	unsigned long committer_time;
+	time_t committer_time;
 	struct strbuf committer_tz;
 
 	struct strbuf summary;
@@ -1587,7 +1587,7 @@ struct commit_info {
  */
 static void get_ac_line(const char *inbuf, const char *what,
 	struct strbuf *name, struct strbuf *mail,
-	unsigned long *time, struct strbuf *tz)
+	time_t *time, struct strbuf *tz)
 {
 	struct ident_split ident;
 	size_t len, maillen, namelen;
@@ -1846,7 +1846,7 @@ static void assign_blame(struct scoreboard *sb, int opt)
 	stop_progress(&pi.progress);
 }
 
-static const char *format_time(unsigned long time, const char *tz_str,
+static const char *format_time(time_t time, const char *tz_str,
 			       int show_raw_time)
 {
 	static struct strbuf time_buf = STRBUF_INIT;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 5413c76e7a6..42452744d67 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -397,7 +397,7 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type,
 static int default_refs;
 
 static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1,
-	unsigned long timestamp)
+	time_t timestamp)
 {
 	struct object *obj;
 
@@ -418,7 +418,7 @@ static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1,
 }
 
 static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
-		const char *email, unsigned long timestamp, int tz,
+		const char *email, time_t timestamp, int tz,
 		const char *message, void *cb_data)
 {
 	const char *refname = cb_data;
diff --git a/builtin/gc.c b/builtin/gc.c
index 331f2192607..7be9d106c0b 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -67,7 +67,7 @@ static void git_config_date_string(const char *key, const char **output)
 	if (git_config_get_string_const(key, output))
 		return;
 	if (strcmp(*output, "now")) {
-		unsigned long now = approxidate("now");
+		time_t now = approxidate("now");
 		if (approxidate(*output) >= now)
 			git_die_config(key, _("Invalid %s: '%s'"), key, *output);
 	}
diff --git a/builtin/log.c b/builtin/log.c
index 24612c2299a..c0d3143d0e3 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -904,7 +904,7 @@ static void gen_message_id(struct rev_info *info, char *base)
 {
 	struct strbuf buf = STRBUF_INIT;
 	strbuf_addf(&buf, "%s.%"PRItime".git.%s", base,
-		    (unsigned long) time(NULL),
+		    (time_t) time(NULL),
 		    git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT));
 	info->message_id = strbuf_detach(&buf, NULL);
 }
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index b572a37c261..5a9580230c8 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -132,7 +132,7 @@ static void add_one_commit(unsigned char *sha1, struct rev_collect *revs)
 }
 
 static int collect_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
-				  const char *ident, unsigned long timestamp,
+				  const char *ident, time_t timestamp,
 				  int tz, const char *message, void *cbdata)
 {
 	struct rev_collect *revs = cbdata;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index a0f16407b93..5faafeda96f 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -10,7 +10,7 @@
 
 typedef struct rev_name {
 	const char *tip_name;
-	unsigned long taggerdate;
+	time_t taggerdate;
 	int generation;
 	int distance;
 } rev_name;
@@ -21,7 +21,7 @@ static long cutoff = LONG_MAX;
 #define MERGE_TRAVERSAL_WEIGHT 65535
 
 static void name_rev(struct commit *commit,
-		const char *tip_name, unsigned long taggerdate,
+		const char *tip_name, time_t taggerdate,
 		int generation, int distance,
 		int deref)
 {
@@ -145,7 +145,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
 	struct name_ref_data *data = cb_data;
 	int can_abbreviate_output = data->tags_only && data->name_only;
 	int deref = 0;
-	unsigned long taggerdate = TIME_MAX;
+	time_t taggerdate = TIME_MAX;
 
 	if (data->tags_only && !starts_with(path, "refs/tags/"))
 		return 0;
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 8841f8b366b..e46ed73f51b 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -44,7 +44,7 @@ static uint32_t nr_result, nr_written;
 static int non_empty;
 static int reuse_delta = 1, reuse_object = 1;
 static int keep_unreachable, unpack_unreachable, include_tag;
-static unsigned long unpack_unreachable_expiration;
+static time_t unpack_unreachable_expiration;
 static int pack_loose_unreachable;
 static int local;
 static int have_non_local_packs;
@@ -2593,7 +2593,7 @@ static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
 static struct sha1_array recent_objects;
 
 static int loosened_object_can_be_discarded(const unsigned char *sha1,
-					    unsigned long mtime)
+					    time_t mtime)
 {
 	if (!unpack_unreachable_expiration)
 		return 0;
diff --git a/builtin/prune.c b/builtin/prune.c
index 1e5eb0292b1..a8babb1f201 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -13,7 +13,7 @@ static const char * const prune_usage[] = {
 };
 static int show_only;
 static int verbose;
-static unsigned long expire;
+static time_t expire;
 static int show_progress = -1;
 
 static int prune_tmp_file(const char *fullpath)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 4a878645847..1b21617c601 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -77,7 +77,7 @@ static const char *NONCE_OK = "OK";
 static const char *NONCE_SLOP = "SLOP";
 static const char *nonce_status;
 static long nonce_stamp_slop;
-static unsigned long nonce_stamp_slop_limit;
+static time_t nonce_stamp_slop_limit;
 static struct ref_transaction *transaction;
 
 static enum {
@@ -451,7 +451,7 @@ static void hmac_sha1(unsigned char *out,
 	git_SHA1_Final(out, &ctx);
 }
 
-static char *prepare_push_cert_nonce(const char *path, unsigned long stamp)
+static char *prepare_push_cert_nonce(const char *path, time_t stamp)
 {
 	struct strbuf buf = STRBUF_INIT;
 	unsigned char sha1[20];
@@ -493,7 +493,7 @@ static char *find_header(const char *msg, size_t len, const char *key)
 static const char *check_nonce(const char *buf, size_t len)
 {
 	char *nonce = find_header(buf, len, "nonce");
-	unsigned long stamp, ostamp;
+	time_t stamp, ostamp;
 	char *bohmac, *expect = NULL;
 	const char *retval = NONCE_BAD;
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 7a7136e53e2..331c874174e 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -16,14 +16,14 @@ static const char reflog_delete_usage[] =
 static const char reflog_exists_usage[] =
 "git reflog exists <ref>";
 
-static unsigned long default_reflog_expire;
-static unsigned long default_reflog_expire_unreachable;
+static time_t default_reflog_expire;
+static time_t default_reflog_expire_unreachable;
 
 struct cmd_reflog_expire_cb {
 	struct rev_info revs;
 	int stalefix;
-	unsigned long expire_total;
-	unsigned long expire_unreachable;
+	time_t expire_total;
+	time_t expire_unreachable;
 	int recno;
 };
 
@@ -219,7 +219,7 @@ static int keep_entry(struct commit **it, unsigned char *sha1)
 static void mark_reachable(struct expire_reflog_policy_cb *cb)
 {
 	struct commit_list *pending;
-	unsigned long expire_limit = cb->mark_limit;
+	time_t expire_limit = cb->mark_limit;
 	struct commit_list *leftover = NULL;
 
 	for (pending = cb->mark_list; pending; pending = pending->next)
@@ -284,7 +284,7 @@ static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit
  * Return true iff the specified reflog entry should be expired.
  */
 static int should_expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
-				    const char *email, unsigned long timestamp, int tz,
+				    const char *email, time_t timestamp, int tz,
 				    const char *message, void *cb_data)
 {
 	struct expire_reflog_policy_cb *cb = cb_data;
@@ -392,8 +392,8 @@ static int collect_reflog(const char *ref, const struct object_id *oid, int unus
 
 static struct reflog_expire_cfg {
 	struct reflog_expire_cfg *next;
-	unsigned long expire_total;
-	unsigned long expire_unreachable;
+	time_t expire_total;
+	time_t expire_unreachable;
 	char pattern[FLEX_ARRAY];
 } *reflog_expire_cfg, **reflog_expire_cfg_tail;
 
@@ -415,7 +415,7 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)
 	return ent;
 }
 
-static int parse_expire_cfg_value(const char *var, const char *value, unsigned long *expire)
+static int parse_expire_cfg_value(const char *var, const char *value, time_t *expire)
 {
 	if (!value)
 		return config_error_nonbool(var);
@@ -433,7 +433,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)
 {
 	const char *pattern, *key;
 	int pattern_len;
-	unsigned long expire;
+	time_t expire;
 	int slot;
 	struct reflog_expire_cfg *ent;
 
@@ -515,7 +515,7 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, c
 static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
 {
 	struct expire_reflog_policy_cb cb;
-	unsigned long now = time(NULL);
+	time_t now = time(NULL);
 	int i, status, do_all;
 	int explicit_expiry = 0;
 	unsigned int flags = 0;
@@ -616,7 +616,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
 }
 
 static int count_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
-		const char *email, unsigned long timestamp, int tz,
+		const char *email, time_t timestamp, int tz,
 		const char *message, void *cb_data)
 {
 	struct expire_reflog_policy_cb *cb = cb_data;
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 974f3403abe..512b5e3db34 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -742,7 +742,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 			base = strtoul(reflog_base, &ep, 10);
 			if (*ep) {
 				/* Ah, that is a date spec... */
-				unsigned long at;
+				time_t at;
 				at = approxidate(reflog_base);
 				read_ref_at(ref, flags, at, -1, oid.hash, NULL,
 					    NULL, NULL, &base);
@@ -753,7 +753,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 			char *logmsg;
 			char *nth_desc;
 			const char *msg;
-			unsigned long timestamp;
+			time_t timestamp;
 			int tz;
 
 			if (read_ref_at(ref, flags, 0, base+i, oid.hash, &logmsg,
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 3df95e112e5..f12a0e4689c 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -30,7 +30,7 @@ struct add_opts {
 
 static int show_only;
 static int verbose;
-static unsigned long expire;
+static time_t expire;
 
 static int prune_worktree(const char *id, struct strbuf *reason)
 {
diff --git a/bundle.c b/bundle.c
index f43bfcf5ff3..75b82e6b653 100644
--- a/bundle.c
+++ b/bundle.c
@@ -211,7 +211,7 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
 	unsigned long size;
 	enum object_type type;
 	char *buf = NULL, *line, *lineend;
-	unsigned long date;
+	time_t date;
 	int result = 1;
 
 	if (revs->max_age == -1 && revs->min_age == -1)
diff --git a/cache.h b/cache.h
index 61fc86e6d71..a276d1ea1b0 100644
--- a/cache.h
+++ b/cache.h
@@ -1361,18 +1361,18 @@ struct date_mode {
 #define DATE_MODE(t) date_mode_from_type(DATE_##t)
 struct date_mode *date_mode_from_type(enum date_mode_type type);
 
-const char *show_date(unsigned long time, int timezone, const struct date_mode *mode);
-void show_date_relative(unsigned long time, int tz, const struct timeval *now,
+const char *show_date(time_t time, int timezone, const struct date_mode *mode);
+void show_date_relative(time_t time, int tz, const struct timeval *now,
 			struct strbuf *timebuf);
 int parse_date(const char *date, struct strbuf *out);
-int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
-int parse_expiry_date(const char *date, unsigned long *timestamp);
+int parse_date_basic(const char *date, time_t *timestamp, int *offset);
+int parse_expiry_date(const char *date, time_t *timestamp);
 void datestamp(struct strbuf *out);
 #define approxidate(s) approxidate_careful((s), NULL)
-unsigned long approxidate_careful(const char *, int *);
-unsigned long approxidate_relative(const char *date, const struct timeval *now);
+time_t approxidate_careful(const char *, int *);
+time_t approxidate_relative(const char *date, const struct timeval *now);
 void parse_date_format(const char *format, struct date_mode *mode);
-int date_overflows(unsigned long date);
+int date_overflows(time_t date);
 
 #define IDENT_STRICT	       1
 #define IDENT_NO_DATE	       2
diff --git a/commit.c b/commit.c
index 7f56b643704..ab379e9d6f4 100644
--- a/commit.c
+++ b/commit.c
@@ -66,7 +66,7 @@ struct commit *lookup_commit_reference_by_name(const char *name)
 	return commit;
 }
 
-static unsigned long parse_commit_date(const char *buf, const char *tail)
+static time_t parse_commit_date(const char *buf, const char *tail)
 {
 	const char *dateptr;
 
@@ -474,8 +474,8 @@ struct commit_list * commit_list_insert_by_date(struct commit *item, struct comm
 
 static int commit_list_compare_by_date(const void *a, const void *b)
 {
-	unsigned long a_date = ((const struct commit_list *)a)->item->date;
-	unsigned long b_date = ((const struct commit_list *)b)->item->date;
+	time_t a_date = ((const struct commit_list *)a)->item->date;
+	time_t b_date = ((const struct commit_list *)b)->item->date;
 	if (a_date < b_date)
 		return 1;
 	if (a_date > b_date)
@@ -599,7 +599,7 @@ static void record_author_date(struct author_date_slab *author_date,
 	const char *ident_line;
 	size_t ident_len;
 	char *date_end;
-	unsigned long date;
+	time_t date;
 
 	ident_line = find_commit_header(buffer, "author", &ident_len);
 	if (!ident_line)
@@ -622,8 +622,8 @@ static int compare_commits_by_author_date(const void *a_, const void *b_,
 {
 	const struct commit *a = a_, *b = b_;
 	struct author_date_slab *author_date = cb_data;
-	unsigned long a_date = *(author_date_slab_at(author_date, a));
-	unsigned long b_date = *(author_date_slab_at(author_date, b));
+	time_t a_date = *(author_date_slab_at(author_date, a));
+	time_t b_date = *(author_date_slab_at(author_date, b));
 
 	/* newer commits with larger date first */
 	if (a_date < b_date)
diff --git a/commit.h b/commit.h
index 9c12abb9111..7b2d3d0b8a8 100644
--- a/commit.h
+++ b/commit.h
@@ -17,7 +17,7 @@ struct commit {
 	struct object object;
 	void *util;
 	unsigned int index;
-	unsigned long date;
+	time_t date;
 	struct commit_list *parents;
 	struct tree *tree;
 };
diff --git a/config.mak.uname b/config.mak.uname
index 447f36ac2e3..ea1a71a936b 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -370,6 +370,7 @@ ifeq ($(uname_S),Windows)
 	NO_INET_PTON = YesPlease
 	NO_INET_NTOP = YesPlease
 	NO_POSIX_GOODIES = UnfortunatelyYes
+	TIME_T_IS_INT64 = YesItIs
 	NATIVE_CRLF = YesPlease
 	DEFAULT_HELP_FORMAT = html
 
@@ -520,6 +521,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	NO_INET_PTON = YesPlease
 	NO_INET_NTOP = YesPlease
 	NO_POSIX_GOODIES = UnfortunatelyYes
+	TIME_T_IS_INT64 = YesItIs
 	DEFAULT_HELP_FORMAT = html
 	COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
diff --git a/credential-cache--daemon.c b/credential-cache--daemon.c
index b298ac01e4f..364e5e0c5be 100644
--- a/credential-cache--daemon.c
+++ b/credential-cache--daemon.c
@@ -8,7 +8,7 @@ static struct tempfile socket_file;
 
 struct credential_cache_entry {
 	struct credential item;
-	unsigned long expiration;
+	time_t expiration;
 };
 static struct credential_cache_entry *entries;
 static int entries_nr;
@@ -47,12 +47,12 @@ static void remove_credential(const struct credential *c)
 		e->expiration = 0;
 }
 
-static int check_expirations(void)
+static time_t check_expirations(void)
 {
-	static unsigned long wait_for_entry_until;
+	static time_t wait_for_entry_until;
 	int i = 0;
-	unsigned long now = time(NULL);
-	unsigned long next = TIME_MAX;
+	time_t now = time(NULL);
+	time_t next = TIME_MAX;
 
 	/*
 	 * Initially give the client 30 seconds to actually contact us
@@ -159,7 +159,7 @@ static void serve_one_client(FILE *in, FILE *out)
 static int serve_cache_loop(int fd)
 {
 	struct pollfd pfd;
-	unsigned long wakeup;
+	time_t wakeup;
 
 	wakeup = check_expirations();
 	if (!wakeup)
diff --git a/date.c b/date.c
index 23dee2964c1..dad2d0c807e 100644
--- a/date.c
+++ b/date.c
@@ -39,7 +39,7 @@ static const char *weekday_names[] = {
 	"Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays"
 };
 
-static time_t gm_time_t(unsigned long time, int tz)
+static time_t gm_time_t(time_t time, int tz)
 {
 	int minutes;
 
@@ -54,7 +54,7 @@ static time_t gm_time_t(unsigned long time, int tz)
  * thing, which means that tz -0100 is passed in as the integer -100,
  * even though it means "sixty minutes off"
  */
-static struct tm *time_to_tm(unsigned long time, int tz)
+static struct tm *time_to_tm(time_t time, int tz)
 {
 	time_t t = gm_time_t(time, tz);
 	return gmtime(&t);
@@ -64,7 +64,7 @@ static struct tm *time_to_tm(unsigned long time, int tz)
  * What value of "tz" was in effect back then at "time" in the
  * local timezone?
  */
-static int local_tzoffset(unsigned long time)
+static int local_tzoffset(time_t time)
 {
 	time_t t, t_local;
 	struct tm tm;
@@ -88,11 +88,11 @@ static int local_tzoffset(unsigned long time)
 	return offset * eastwest;
 }
 
-void show_date_relative(unsigned long time, int tz,
+void show_date_relative(time_t time, int tz,
 			       const struct timeval *now,
 			       struct strbuf *timebuf)
 {
-	unsigned long diff;
+	time_t diff;
 	if (now->tv_sec < time) {
 		strbuf_addstr(timebuf, _("in the future"));
 		return;
@@ -140,9 +140,9 @@ void show_date_relative(unsigned long time, int tz,
 	}
 	/* Give years and months for 5 years or so */
 	if (diff < 1825) {
-		unsigned long totalmonths = (diff * 12 * 2 + 365) / (365 * 2);
-		unsigned long years = totalmonths / 12;
-		unsigned long months = totalmonths % 12;
+		time_t totalmonths = (diff * 12 * 2 + 365) / (365 * 2);
+		time_t years = totalmonths / 12;
+		time_t months = totalmonths % 12;
 		if (months) {
 			struct strbuf sb = STRBUF_INIT;
 			strbuf_addf(&sb, Q_("%"PRItime" year", "%"PRItime" years", years), years);
@@ -172,7 +172,7 @@ struct date_mode *date_mode_from_type(enum date_mode_type type)
 	return &mode;
 }
 
-const char *show_date(unsigned long time, int tz, const struct date_mode *mode)
+const char *show_date(time_t time, int tz, const struct date_mode *mode)
 {
 	struct tm *tm;
 	static struct strbuf timebuf = STRBUF_INIT;
@@ -425,7 +425,7 @@ static int is_date(int year, int month, int day, struct tm *now_tm, time_t now,
 	return 0;
 }
 
-static int match_multi_number(unsigned long num, char c, const char *date,
+static int match_multi_number(time_t num, char c, const char *date,
 			      char *end, struct tm *tm, time_t now)
 {
 	struct tm now_tm;
@@ -508,7 +508,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
 {
 	int n;
 	char *end;
-	unsigned long num;
+	time_t num;
 
 	num = parse_timestamp(date, &end, 10);
 
@@ -635,7 +635,7 @@ static int match_tz(const char *date, int *offp)
 	return end - date;
 }
 
-static void date_string(unsigned long date, int offset, struct strbuf *buf)
+static void date_string(time_t date, int offset, struct strbuf *buf)
 {
 	int sign = '+';
 
@@ -650,10 +650,10 @@ static void date_string(unsigned long date, int offset, struct strbuf *buf)
  * Parse a string like "0 +0000" as ancient timestamp near epoch, but
  * only when it appears not as part of any other string.
  */
-static int match_object_header_date(const char *date, unsigned long *timestamp, int *offset)
+static int match_object_header_date(const char *date, time_t *timestamp, int *offset)
 {
 	char *end;
-	unsigned long stamp;
+	time_t stamp;
 	int ofs;
 
 	if (*date < '0' || '9' < *date)
@@ -675,11 +675,11 @@ static int match_object_header_date(const char *date, unsigned long *timestamp,
 
 /* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
    (i.e. English) day/month names, and it doesn't work correctly with %z. */
-int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
+int parse_date_basic(const char *date, time_t *timestamp, int *offset)
 {
 	struct tm tm;
 	int tm_gmt;
-	unsigned long dummy_timestamp;
+	time_t dummy_timestamp;
 	int dummy_offset;
 
 	if (!timestamp)
@@ -747,7 +747,7 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
 	return 0; /* success */
 }
 
-int parse_expiry_date(const char *date, unsigned long *timestamp)
+int parse_expiry_date(const char *date, time_t *timestamp)
 {
 	int errors = 0;
 
@@ -771,7 +771,7 @@ int parse_expiry_date(const char *date, unsigned long *timestamp)
 
 int parse_date(const char *date, struct strbuf *result)
 {
-	unsigned long timestamp;
+	time_t timestamp;
 	int offset;
 	if (parse_date_basic(date, &timestamp, &offset))
 		return -1;
@@ -845,7 +845,7 @@ void datestamp(struct strbuf *out)
  * Relative time update (eg "2 days ago").  If we haven't set the time
  * yet, we need to set it from current time.
  */
-static unsigned long update_tm(struct tm *tm, struct tm *now, unsigned long sec)
+static time_t update_tm(struct tm *tm, struct tm *now, time_t sec)
 {
 	time_t n;
 
@@ -1114,7 +1114,7 @@ static void pending_number(struct tm *tm, int *num)
 	}
 }
 
-static unsigned long approxidate_str(const char *date,
+static time_t approxidate_str(const char *date,
 				     const struct timeval *tv,
 				     int *error_ret)
 {
@@ -1151,9 +1151,9 @@ static unsigned long approxidate_str(const char *date,
 	return update_tm(&tm, &now, 0);
 }
 
-unsigned long approxidate_relative(const char *date, const struct timeval *tv)
+time_t approxidate_relative(const char *date, const struct timeval *tv)
 {
-	unsigned long timestamp;
+	time_t timestamp;
 	int offset;
 	int errors = 0;
 
@@ -1162,10 +1162,10 @@ unsigned long approxidate_relative(const char *date, const struct timeval *tv)
 	return approxidate_str(date, tv, &errors);
 }
 
-unsigned long approxidate_careful(const char *date, int *error_ret)
+time_t approxidate_careful(const char *date, int *error_ret)
 {
 	struct timeval tv;
-	unsigned long timestamp;
+	time_t timestamp;
 	int offset;
 	int dummy = 0;
 	if (!error_ret)
@@ -1180,7 +1180,7 @@ unsigned long approxidate_careful(const char *date, int *error_ret)
 	return approxidate_str(date, &tv, error_ret);
 }
 
-int date_overflows(unsigned long t)
+int date_overflows(time_t t)
 {
 	time_t sys;
 
diff --git a/fetch-pack.c b/fetch-pack.c
index 54fb35e39c5..d3401733b05 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -356,7 +356,7 @@ static int find_common(struct fetch_pack_args *args,
 	if (args->depth > 0)
 		packet_buf_write(&req_buf, "deepen %d", args->depth);
 	if (args->deepen_since) {
-		unsigned long max_age = approxidate(args->deepen_since);
+		time_t max_age = approxidate(args->deepen_since);
 		packet_buf_write(&req_buf, "deepen-since %"PRItime, max_age);
 	}
 	if (args->deepen_not) {
@@ -545,7 +545,7 @@ static int mark_complete_oid(const char *refname, const struct object_id *oid,
 }
 
 static void mark_recent_complete_commits(struct fetch_pack_args *args,
-					 unsigned long cutoff)
+					 time_t cutoff)
 {
 	while (complete && cutoff <= complete->item->date) {
 		print_verbose(args, _("Marking %s as complete"),
@@ -630,7 +630,7 @@ static int everything_local(struct fetch_pack_args *args,
 {
 	struct ref *ref;
 	int retval;
-	unsigned long cutoff = 0;
+	time_t cutoff = 0;
 
 	save_commit_buffer = 0;
 
diff --git a/git-compat-util.h b/git-compat-util.h
index 5cf1133532d..027f3b2f8eb 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -326,7 +326,7 @@ extern char *gitdirname(char *);
 #else
 #define PRItime "lu"
 #define parse_timestamp strtoul
-#define TIME_MAX ULONG_MAX
+#define TIME_MAX LONG_MAX
 #endif
 
 #ifndef PATH_SEP
diff --git a/http-backend.c b/http-backend.c
index eef0a361f4f..4e88735a9e3 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -90,7 +90,7 @@ static void hdr_int(struct strbuf *hdr, const char *name, uintmax_t value)
 	strbuf_addf(hdr, "%s: %" PRIuMAX "\r\n", name, value);
 }
 
-static void hdr_date(struct strbuf *hdr, const char *name, unsigned long when)
+static void hdr_date(struct strbuf *hdr, const char *name, time_t when)
 {
 	const char *value = show_date(when, 0, DATE_MODE(RFC2822));
 	hdr_str(hdr, name, value);
@@ -105,7 +105,7 @@ static void hdr_nocache(struct strbuf *hdr)
 
 static void hdr_cache_forever(struct strbuf *hdr)
 {
-	unsigned long now = time(NULL);
+	time_t now = time(NULL);
 	hdr_date(hdr, "Date", now);
 	hdr_date(hdr, "Expires", now + 31536000);
 	hdr_str(hdr, "Cache-Control", "public, max-age=31536000");
diff --git a/parse-options-cb.c b/parse-options-cb.c
index b7d8f7dcb2c..a560d8d0b8c 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -31,14 +31,14 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
 int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
 			     int unset)
 {
-	*(unsigned long *)(opt->value) = approxidate(arg);
+	*(time_t *)(opt->value) = approxidate(arg);
 	return 0;
 }
 
 int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,
 			     int unset)
 {
-	return parse_expiry_date(arg, (unsigned long *)opt->value);
+	return parse_expiry_date(arg, (time_t *)opt->value);
 }
 
 int parse_opt_color_flag_cb(const struct option *opt, const char *arg,
diff --git a/pretty.c b/pretty.c
index 6d1e1e87e7d..ab689009536 100644
--- a/pretty.c
+++ b/pretty.c
@@ -405,7 +405,7 @@ static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
 const char *show_ident_date(const struct ident_split *ident,
 			    const struct date_mode *mode)
 {
-	unsigned long date = 0;
+	time_t date = 0;
 	long tz = 0;
 
 	if (ident->date_begin && ident->date_end)
diff --git a/reachable.c b/reachable.c
index d0199cace4a..f4d2be6beb7 100644
--- a/reachable.c
+++ b/reachable.c
@@ -55,12 +55,11 @@ static void mark_commit(struct commit *c, void *data)
 
 struct recent_data {
 	struct rev_info *revs;
-	unsigned long timestamp;
+	time_t timestamp;
 };
 
 static void add_recent_object(const unsigned char *sha1,
-			      unsigned long mtime,
-			      struct recent_data *data)
+			      time_t mtime, struct recent_data *data)
 {
 	struct object *obj;
 	enum object_type type;
@@ -139,7 +138,7 @@ static int add_recent_packed(const unsigned char *sha1,
 }
 
 int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
-					   unsigned long timestamp)
+					   time_t timestamp)
 {
 	struct recent_data data;
 	int r;
@@ -156,8 +155,7 @@ int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
 }
 
 void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
-			    unsigned long mark_recent,
-			    struct progress *progress)
+			    time_t mark_recent, struct progress *progress)
 {
 	struct connectivity_progress cp;
 
diff --git a/reachable.h b/reachable.h
index d23efc36ec5..2a7f6588941 100644
--- a/reachable.h
+++ b/reachable.h
@@ -3,8 +3,8 @@
 
 struct progress;
 extern int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
-						  unsigned long timestamp);
+						  time_t timestamp);
 extern void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
-				   unsigned long mark_recent, struct progress *);
+				   time_t mark_recent, struct progress *);
 
 #endif
diff --git a/ref-filter.c b/ref-filter.c
index b8b34d4dd9e..265b7c03845 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -618,7 +618,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
 {
 	const char *eoemail = strstr(buf, "> ");
 	char *zone;
-	unsigned long timestamp;
+	time_t timestamp;
 	long tz;
 	struct date_mode date_mode = { DATE_NORMAL };
 	const char *formatp;
diff --git a/reflog-walk.c b/reflog-walk.c
index a246af27678..d1a8673c348 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -12,7 +12,7 @@ struct complete_reflogs {
 	struct reflog_info {
 		unsigned char osha1[20], nsha1[20];
 		char *email;
-		unsigned long timestamp;
+		time_t timestamp;
 		int tz;
 		char *message;
 	} *items;
@@ -20,7 +20,7 @@ struct complete_reflogs {
 };
 
 static int read_one_reflog(unsigned char *osha1, unsigned char *nsha1,
-		const char *email, unsigned long timestamp, int tz,
+		const char *email, time_t timestamp, int tz,
 		const char *message, void *cb_data)
 {
 	struct complete_reflogs *array = cb_data;
@@ -69,7 +69,7 @@ static struct complete_reflogs *read_complete_reflog(const char *ref)
 }
 
 static int get_reflog_recno_by_time(struct complete_reflogs *array,
-	unsigned long timestamp)
+	time_t timestamp)
 {
 	int i;
 	for (i = array->nr - 1; i >= 0; i--)
@@ -141,7 +141,7 @@ void init_reflog_walk(struct reflog_walk_info **info)
 int add_reflog_for_walk(struct reflog_walk_info *info,
 		struct commit *commit, const char *name)
 {
-	unsigned long timestamp = 0;
+	time_t timestamp = 0;
 	int recno = -1;
 	struct string_list_item *item;
 	struct complete_reflogs *reflogs;
diff --git a/refs.c b/refs.c
index cd36b64ed93..546e9080555 100644
--- a/refs.c
+++ b/refs.c
@@ -658,7 +658,7 @@ int is_branch(const char *refname)
 
 struct read_ref_at_cb {
 	const char *refname;
-	unsigned long at_time;
+	time_t at_time;
 	int cnt;
 	int reccnt;
 	unsigned char *sha1;
@@ -667,15 +667,15 @@ struct read_ref_at_cb {
 	unsigned char osha1[20];
 	unsigned char nsha1[20];
 	int tz;
-	unsigned long date;
+	time_t date;
 	char **msg;
-	unsigned long *cutoff_time;
+	time_t *cutoff_time;
 	int *cutoff_tz;
 	int *cutoff_cnt;
 };
 
 static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
-		const char *email, unsigned long timestamp, int tz,
+		const char *email, time_t timestamp, int tz,
 		const char *message, void *cb_data)
 {
 	struct read_ref_at_cb *cb = cb_data;
@@ -722,7 +722,7 @@ static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
 }
 
 static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
-				  const char *email, unsigned long timestamp,
+				  const char *email, time_t timestamp,
 				  int tz, const char *message, void *cb_data)
 {
 	struct read_ref_at_cb *cb = cb_data;
@@ -742,9 +742,9 @@ static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
 	return 1;
 }
 
-int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time, int cnt,
+int read_ref_at(const char *refname, unsigned int flags, time_t at_time, int cnt,
 		unsigned char *sha1, char **msg,
-		unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
+		time_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
 {
 	struct read_ref_at_cb cb;
 
diff --git a/refs.h b/refs.h
index 9fbff90e79b..1748827a7ba 100644
--- a/refs.h
+++ b/refs.h
@@ -262,9 +262,9 @@ int safe_create_reflog(const char *refname, int force_create, struct strbuf *err
 
 /** Reads log for the value of ref during at_time. **/
 int read_ref_at(const char *refname, unsigned int flags,
-		unsigned long at_time, int cnt,
+		time_t at_time, int cnt,
 		unsigned char *sha1, char **msg,
-		unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
+		time_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
 
 /** Check if a particular reflog exists */
 int reflog_exists(const char *refname);
@@ -293,7 +293,7 @@ int delete_reflog(const char *refname);
 /* iterate over reflog entries */
 typedef int each_reflog_ent_fn(
 		unsigned char *old_sha1, unsigned char *new_sha1,
-		const char *committer, unsigned long timestamp,
+		const char *committer, time_t timestamp,
 		int tz, const char *msg, void *cb_data);
 
 int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data);
@@ -536,7 +536,7 @@ typedef void reflog_expiry_prepare_fn(const char *refname,
 typedef int reflog_expiry_should_prune_fn(unsigned char *osha1,
 					  unsigned char *nsha1,
 					  const char *email,
-					  unsigned long timestamp, int tz,
+					  time_t timestamp, int tz,
 					  const char *message, void *cb_data);
 typedef void reflog_expiry_cleanup_fn(void *cb_data);
 
diff --git a/refs/files-backend.c b/refs/files-backend.c
index c041d4ba21a..4316de3a692 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3115,7 +3115,7 @@ static int show_one_reflog_ent(struct strbuf *sb, each_reflog_ent_fn fn, void *c
 {
 	unsigned char osha1[20], nsha1[20];
 	char *email_end, *message;
-	unsigned long timestamp;
+	time_t timestamp;
 	int tz;
 
 	/* old SP new SP name <email> SP time TAB msg LF */
@@ -3940,7 +3940,7 @@ struct expire_reflog_cb {
 };
 
 static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
-			     const char *email, unsigned long timestamp, int tz,
+			     const char *email, time_t timestamp, int tz,
 			     const char *message, void *cb_data)
 {
 	struct expire_reflog_cb *cb = cb_data;
diff --git a/revision.c b/revision.c
index b37dbec378f..419d5fa954e 100644
--- a/revision.c
+++ b/revision.c
@@ -884,7 +884,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
 /* How many extra uninteresting commits we want to see.. */
 #define SLOP 5
 
-static int still_interesting(struct commit_list *src, unsigned long date, int slop,
+static int still_interesting(struct commit_list *src, time_t date, int slop,
 			     struct commit **interesting_cache)
 {
 	/*
@@ -1018,7 +1018,7 @@ static void limit_left_right(struct commit_list *list, struct rev_info *revs)
 static int limit_list(struct rev_info *revs)
 {
 	int slop = SLOP;
-	unsigned long date = ~0ul;
+	time_t date = ~0ul;
 	struct commit_list *list = revs->commits;
 	struct commit_list *newlist = NULL;
 	struct commit_list **p = &newlist;
@@ -1215,7 +1215,7 @@ static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data)
 }
 
 static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
-		const char *email, unsigned long timestamp, int tz,
+		const char *email, time_t timestamp, int tz,
 		const char *message, void *cb_data)
 {
 	handle_one_reflog_commit(osha1, cb_data);
diff --git a/revision.h b/revision.h
index 9fac1a607de..e39e5b524bb 100644
--- a/revision.h
+++ b/revision.h
@@ -181,8 +181,8 @@ struct rev_info {
 	/* special limits */
 	int skip_count;
 	int max_count;
-	unsigned long max_age;
-	unsigned long min_age;
+	time_t max_age;
+	time_t min_age;
 	int min_parents;
 	int max_parents;
 	int (*include_check)(struct commit *, void *);
diff --git a/sha1_name.c b/sha1_name.c
index 73a915ff1b3..9520586139e 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -658,8 +658,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
 
 	if (reflog_len) {
 		int nth, i;
-		unsigned long at_time;
-		unsigned long co_time;
+		time_t at_time;
+		time_t co_time;
 		int co_tz, co_cnt;
 
 		/* Is it asking for N-th entry, or approxidate? */
@@ -1052,7 +1052,7 @@ struct grab_nth_branch_switch_cbdata {
 };
 
 static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
-				  const char *email, unsigned long timestamp, int tz,
+				  const char *email, time_t timestamp, int tz,
 				  const char *message, void *cb_data)
 {
 	struct grab_nth_branch_switch_cbdata *cb = cb_data;
diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index ba309ec1760..371f9d259c6 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -47,7 +47,7 @@ static void parse_dates(const char **argv, struct timeval *now)
 	struct strbuf result = STRBUF_INIT;
 
 	for (; *argv; argv++) {
-		unsigned long t;
+		time_t t;
 		int tz;
 
 		strbuf_reset(&result);
@@ -95,7 +95,7 @@ int cmd_main(int argc, const char **argv)
 	else if (!strcmp(*argv, "approxidate"))
 		parse_approxidate(argv+1, &now);
 	else if (!strcmp(*argv, "is64bit"))
-		return sizeof(unsigned long) == 8 ? 0 : 1;
+		return sizeof(time_t) == 8 ? 0 : 1;
 	else
 		usage(usage_msg);
 	return 0;
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index 7d93627e454..8af62dd7501 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -5,7 +5,7 @@
 static int boolean = 0;
 static int integer = 0;
 static unsigned long magnitude = 0;
-static unsigned long timestamp;
+static time_t timestamp;
 static int abbrev = 7;
 static int verbose = -1; /* unspecified */
 static int dry_run = 0, quiet = 0;
diff --git a/tag.c b/tag.c
index 55d07725777..a0b22c788b6 100644
--- a/tag.c
+++ b/tag.c
@@ -97,7 +97,7 @@ struct tag *lookup_tag(const unsigned char *sha1)
 	return object_as_type(obj, OBJ_TAG, 0);
 }
 
-static unsigned long parse_tag_date(const char *buf, const char *tail)
+static time_t parse_tag_date(const char *buf, const char *tail)
 {
 	const char *dateptr;
 
diff --git a/tag.h b/tag.h
index a5721b6731e..aaf56849de8 100644
--- a/tag.h
+++ b/tag.h
@@ -9,7 +9,7 @@ struct tag {
 	struct object object;
 	struct object *tagged;
 	char *tag;
-	unsigned long date;
+	time_t date;
 };
 
 extern struct tag *lookup_tag(const unsigned char *sha1);
diff --git a/upload-pack.c b/upload-pack.c
index c2be661f6d4..4dcc6aa8d95 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -35,7 +35,7 @@ static const char * const upload_pack_usage[] = {
 #define CLIENT_SHALLOW	(1u << 18)
 #define HIDDEN_REF	(1u << 19)
 
-static unsigned long oldest_have;
+static time_t oldest_have;
 
 static int deepen_relative;
 static int multi_ack;
@@ -735,7 +735,7 @@ static void receive_needs(void)
 	struct string_list deepen_not = STRING_LIST_INIT_DUP;
 	int depth = 0;
 	int has_non_tip = 0;
-	unsigned long deepen_since = 0;
+	time_t deepen_since = 0;
 	int deepen_rev_list = 0;
 
 	shallow_nr = 0;
diff --git a/vcs-svn/fast_export.c b/vcs-svn/fast_export.c
index 6c9f2866d8b..5df87ce6bb4 100644
--- a/vcs-svn/fast_export.c
+++ b/vcs-svn/fast_export.c
@@ -68,7 +68,7 @@ void fast_export_modify(const char *path, uint32_t mode, const char *dataref)
 }
 
 void fast_export_begin_note(uint32_t revision, const char *author,
-		const char *log, unsigned long timestamp, const char *note_ref)
+		const char *log, time_t timestamp, const char *note_ref)
 {
 	static int firstnote = 1;
 	size_t loglen = strlen(log);
@@ -93,7 +93,7 @@ static char gitsvnline[MAX_GITSVN_LINE_LEN];
 void fast_export_begin_commit(uint32_t revision, const char *author,
 			const struct strbuf *log,
 			const char *uuid, const char *url,
-			unsigned long timestamp, const char *local_ref)
+			time_t timestamp, const char *local_ref)
 {
 	static const struct strbuf empty = STRBUF_INIT;
 	if (!log)
diff --git a/vcs-svn/fast_export.h b/vcs-svn/fast_export.h
index c8b5adb811c..864dada2b31 100644
--- a/vcs-svn/fast_export.h
+++ b/vcs-svn/fast_export.h
@@ -11,10 +11,10 @@ void fast_export_delete(const char *path);
 void fast_export_modify(const char *path, uint32_t mode, const char *dataref);
 void fast_export_note(const char *committish, const char *dataref);
 void fast_export_begin_note(uint32_t revision, const char *author,
-		const char *log, unsigned long timestamp, const char *note_ref);
+		const char *log, time_t timestamp, const char *note_ref);
 void fast_export_begin_commit(uint32_t revision, const char *author,
 			const struct strbuf *log, const char *uuid,const char *url,
-			unsigned long timestamp, const char *local_ref);
+			time_t timestamp, const char *local_ref);
 void fast_export_end_commit(uint32_t revision);
 void fast_export_data(uint32_t mode, off_t len, struct line_buffer *input);
 void fast_export_buf_to_data(const struct strbuf *data);
diff --git a/vcs-svn/svndump.c b/vcs-svn/svndump.c
index e4b395963b9..9e1eb8d4176 100644
--- a/vcs-svn/svndump.c
+++ b/vcs-svn/svndump.c
@@ -47,7 +47,7 @@ static struct {
 
 static struct {
 	uint32_t revision;
-	unsigned long timestamp;
+	time_t timestamp;
 	struct strbuf log, author, note;
 } rev_ctx;
 
diff --git a/wt-status.c b/wt-status.c
index d47012048f8..da261363551 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1374,7 +1374,7 @@ struct grab_1st_switch_cbdata {
 };
 
 static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1,
-			   const char *email, unsigned long timestamp, int tz,
+			   const char *email, time_t timestamp, int tz,
 			   const char *message, void *cb_data)
 {
 	struct grab_1st_switch_cbdata *cb = cb_data;
-- 
2.11.1.windows.1.379.g44ae0bc

^ permalink raw reply related

* Re: [BUG] branch renamed to 'HEAD'
From: Junio C Hamano @ 2017-02-28  0:33 UTC (permalink / raw)
  To: Jacob Keller; +Cc: Jeff King, Karthik Nayak, Luc Van Oostenryck, Git List
In-Reply-To: <CA+P7+xpVt6NtSajqMX8OQ_SKdC9tfHH40JgK=9DgBxo9nMaWLA@mail.gmail.com>

Jacob Keller <jacob.keller@gmail.com> writes:

> What about changing interpret-branch-name gains a flag to return a
> fully qualified ref rather than returning just the name? That seems
> like it would be more reasonable behavior.

There are two kinds of callers to i-b-n.  The ones that want a local
branch name because they are parsing special places on the command
line that using a local branch name makes difference (as opposed to
using any extended SHA-1 expression), like "git checkout master"
(which means different thing from "git checkout master^0").  And the
ones that can use any object name.

It depends on how your flag works, but if it means "add refs/heads/
when you got a local branch name", then that would not work well for
the former callers, as end-user inputs @{-1} and refs/heads/master
would become indistinguishable.  The former is expanded to 'master'
(if you were on that branch) and ends up being refs/heads/master.
"git checkout refs/heads/master" would be (unless you have a branch
with that name, i.e. refs/heads/refs/heads/master) a request to
detach HEAD at the commit, but the user wanted to be on the previous
branch.  And the latter iclass of callers are probably already happy
with or without the flag, so they won't be helped, either.

A flag to affect the behaviour (as opposed to &flag as a secondary
return value, like Peff's patch does) can be made to work.  Perhaps
a flag that says "keep the input as is if the result is not a local
branch name" would pass an input "@" intact and that may be
sufficient to allow "git branch -m @" to rename the current branch
to "@" (I do not think it is a sensible rename, though ;-).  But
probably some callers need to keep the original input and compare
with the result to see if we expanded anything if we go that route.
At that point, I am not sure if there are much differences in the
ease of use between the two approaches.

^ permalink raw reply

* Re: git diff --quiet exits with 1 on clean tree with CRLF conversions
From: Junio C Hamano @ 2017-02-27 20:17 UTC (permalink / raw)
  To: Torsten Bögershausen; +Cc: git, Mike Crowe
In-Reply-To: <20170225153230.GA30565@mcrowe.com>

Torsten, you've been quite active in fixing various glitches around
the EOL conversion in the latter half of last year.  Have any
thoughts to share on this topic?

Thanks.

Mike Crowe <mac@mcrowe.com> writes:

> On Monday 20 February 2017 at 13:25:01 -0800, Junio C Hamano wrote:
>> This almost makes me suspect that the place that checks lengths of
>> one and two in order to refrain from running more expensive content
>> comparison you found earlier need to ask would_convert_to_git()
>> before taking the short-cut, something along the lines of this (for
>> illustration purposes only, not even compile-tested).  The "almost"
>> comes to me because I do not offhand know the performance implications
>> of making calls to would_convert_to_git() here.
>> 
>>  diff.c | 18 ++++++++++++++----
>>  1 file changed, 14 insertions(+), 4 deletions(-)
>> 
>> diff --git a/diff.c b/diff.c
>> index 051761be40..094d5913da 100644
>> --- a/diff.c
>> +++ b/diff.c
>> @@ -4921,9 +4921,10 @@ static int diff_filespec_check_stat_unmatch(struct diff_filepair *p)
>>  	 *    differences.
>>  	 *
>>  	 * 2. At this point, the file is known to be modified,
>> -	 *    with the same mode and size, and the object
>> -	 *    name of one side is unknown.  Need to inspect
>> -	 *    the identical contents.
>> +	 *    with the same mode and size, the object
>> +	 *    name of one side is unknown, or size comparison
>> +	 *    cannot be depended upon.  Need to inspect the 
>> +	 *    contents.
>>  	 */
>>  	if (!DIFF_FILE_VALID(p->one) || /* (1) */
>>  	    !DIFF_FILE_VALID(p->two) ||
>> @@ -4931,7 +4932,16 @@ static int diff_filespec_check_stat_unmatch(struct diff_filepair *p)
>>  	    (p->one->mode != p->two->mode) ||
>>  	    diff_populate_filespec(p->one, CHECK_SIZE_ONLY) ||
>>  	    diff_populate_filespec(p->two, CHECK_SIZE_ONLY) ||
>> -	    (p->one->size != p->two->size) ||
>> +
>> +	    /* 
>> +	     * only if eol and other conversions are not involved,
>> +	     * we can say that two contents of different sizes
>> +	     * cannot be the same without checking their contents.
>> +	     */
>> +	    (!would_convert_to_git(p->one->path) &&
>> +	     !would_convert_to_git(p->two->path) &&
>> +	     (p->one->size != p->two->size)) ||
>> +
>>  	    !diff_filespec_is_identical(p->one, p->two)) /* (2) */
>>  		p->skip_stat_unmatch_result = 1;
>>  	return p->skip_stat_unmatch_result;
>> 
>> 
>
> Thanks for investigating this. I think you are correct that I was misguided
> in my previous "fix". However, your change above does fix the problem for
> me.
>
> It looks like the main cost of convert_to_git is in convert_attrs which
> ends up doing various path operations in attr.c. After that, both
> apply_filter and crlf_to_git return straight away if there's nothing to do.
>
> I experimented several times with running "git diff -quiet" after touching
> every file in Git's own worktree and any difference in total time was lost
> in the noise.
>
> I've further improved my test case. Tests 3 and 4 fail without the above
> change but pass with it. Unfortunately I'm still unable to get those tests
> to fail without the above fix unless the sleeps are present. I've tried
> using the "touch -r .datetime" technique from racy-git.txt but it doesn't
> help. It seems that I'm unable to stop Git from using its cache without
> sleeping. :(
>
> diff --git a/t/t4063-diff-converted.sh b/t/t4063-diff-converted.sh
> new file mode 100755
> index 0000000..31a730d
> --- /dev/null
> +++ b/t/t4063-diff-converted.sh
> @@ -0,0 +1,44 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2017 Mike Crowe
> +#
> +# These tests ensure that files changing line endings in the presence
> +# of .gitattributes to indicate that line endings should be ignored
> +# don't cause 'git diff' or 'git diff --quiet' to think that they have
> +# been changed.
> +#
> +# The sleeps are necessary to reproduce the problem for reasons that I
> +# don't understand.
> +
> +test_description='git diff with files that require CRLF conversion'
> +
> +. ./test-lib.sh
> +
> +test_expect_success setup '
> +	echo "* text=auto" > .gitattributes &&
> +	printf "Hello\r\nWorld\r\n" > crlf.txt &&
> +	printf "Hello\nWorld\n" > lf.txt &&
> +	git add .gitattributes crlf.txt lf.txt &&
> +	git commit -m "initial" && echo three
> +'
> +test_expect_success 'noisy diff works on file that requires CRLF conversion' '
> +	git status >/dev/null &&
> +	git diff >/dev/null &&
> +	sleep 1 &&
> +	touch crlf.txt lf.txt &&
> +	git diff >/dev/null
> +'
> +test_expect_success 'quiet diff works on file that requires CRLF conversion with no changes' '
> +	git status &&
> +	git diff --quiet &&
> +	sleep 1 &&
> +	touch crlf.txt lf.txt &&
> +	git diff --quiet
> +'
> +
> +test_expect_success 'quiet diff works on file with line-ending change that has no effect on repository' '
> +	printf "Hello\nWorld\n" > crlf.txt &&
> +	printf "Hello\r\nWorld\r\n" > lf.txt &&
> +	git diff --quiet
> +'
> +test_done
>
>
> Mike.

^ permalink raw reply

* Re: [BUG] branch renamed to 'HEAD'
From: Jeff King @ 2017-02-28  0:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Karthik Nayak, Luc Van Oostenryck, Git List
In-Reply-To: <xmqq60jvnu9y.fsf@gitster.mtv.corp.google.com>

On Mon, Feb 27, 2017 at 02:28:09PM -0800, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > I guess something like the patch below works, but I wonder if there is a
> > less-horrible way to accomplish the same thing.
> 
> I suspect that a less-horrible would be a lot more intrusive.  It
> would go like "interpret-branch-name only gives local branch name,
> and when it does not show it, the callers that know they do not
> necessarily need local branch name would call other at-mark things".
> As you pointed out with the @{upstream} that potentially point at a
> local branch, it will quickly get more involved, I would think, and
> I tend to think that this patch of yours is probably the least evil
> one among possible solutions.  
> 
> Perhaps with s/not_in_refs_heads/not_a_branch_name/ (or swapping
> polarity, "is_a_branch_name"), the resulting code may not be too
> hard to read?

I actually started with not_a_branch_name, but I wanted specifically to
talk about refs_heads, because we sometimes refer to remote-tracking
branches as "branches" (and the function is called interpret_branch_name(),
after all).

I agree it would be easier to read if the logic were flipped, but I'm
not sure that would be correct. The function knows when it has done a
replacement that takes us outside of a normal branch name. But when it
hasn't, it doesn't really know how the result should be interpreted.

For our purposes in this caller it is enough to say that "foo" should be
treated as "refs/heads/foo", but I don't think that is generally true of
interpret_branch_name(), which might be called as part of get_sha1().

So one alternative is to leave the logic the same way but try to give it
a better name. E.g., call it something like "replaced_with_non_branch"
or something. But there, another negation snuck in. The correct
non-negated thing is really "replaced_with_HEAD_or_refs_remotes" but
that is rather awkward.

-Peff

^ permalink raw reply

* Re: [BUG] branch renamed to 'HEAD'
From: Jeff King @ 2017-02-28  0:49 UTC (permalink / raw)
  To: Jacob Keller; +Cc: Junio C Hamano, Karthik Nayak, Luc Van Oostenryck, Git List
In-Reply-To: <CA+P7+xpVt6NtSajqMX8OQ_SKdC9tfHH40JgK=9DgBxo9nMaWLA@mail.gmail.com>

On Mon, Feb 27, 2017 at 03:05:37PM -0800, Jacob Keller wrote:

> > Perhaps with s/not_in_refs_heads/not_a_branch_name/ (or swapping
> > polarity, "is_a_branch_name"), the resulting code may not be too
> > hard to read?
> 
> What about changing interpret-branch-name gains a flag to return a
> fully qualified ref rather than returning just the name? That seems
> like it would be more reasonable behavior.

That's not sufficient. If I feed "refs/remotes/origin/master" as a
branch name to git-branch, then as silly as that is, it is the branch
whose ref is "refs/heads/refs/remotes/origin/master".

Since interpret_branch_name() is not fully qualifying everything, but
rather just _sometimes_ replace @-marks with refnames, we cannot tell
from just the string the difference between "the user fed us
refs/remotes/foo" and "the @-mark expanded to a non-branch
refs/remotes/foo". We need one extra bit of information to know whether
an expansion occurred.

You could give a flag that says "do not expand to anything outside of
refs/heads/" that would suppress the @->HEAD mark, as well as
@{upstream} when upstream is outside of refs/heads. That would certainly
be less nasty than the out-parameter, but I wasn't sure that the error
handling was what we wanted.

In strbuf_branchname(), we quietly turn that error into a "0", which
causes us to retain the original text. We then feed that into
check_refname_format() in strbuf_check_branch_ref(). Which I think would
complain, and you'd get "not a valid refname: @{upstream}". If we have
the out-bit, we can say "I understand what @{upstream} means, but it
does not expand to a local branch". That's a more specific error, but
maybe it is not worth the hassle to produce it.

-Peff

^ permalink raw reply

* Re: [PATCH 0/6] Use time_t
From: Junio C Hamano @ 2017-02-27 22:48 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <cover.1488231002.git.johannes.schindelin@gmx.de>

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

> One notable fallout of this patch series is that on 64-bit Linux (and
> other platforms where `unsigned long` is 64-bit), we now limit the range
> of dates to LONG_MAX (i.e. the *signed* maximum value). This needs to be
> done as `time_t` can be signed (and indeed is at least on my Ubuntu
> setup).
>
> Obviously, I think that we can live with that, and I hope that all
> interested parties agree.

s/ulong/time_t/ is definintely a good change, and it will take us to
a place we would want to be in in some future.  

As long as there remains no platform we care about whose time_t and
long are still 32-bit signed integer, there will be a fallout to
them with this change.  Probably it is of a larger impact than
losing the upper half of a 64-bit timestamp range on larger boxes.
Hopefully those platforms have died out (or at least we don't mind
breaking them)?

It appears that we use uint64_t in many places in our code.  So
while philosophically time_t is the right type, uint64_t might be
practically a safer alternative type to use at the endgame patch in
this series.  I haven't seen it yet, but presumably the last one 6/6
is the endgame?



^ permalink raw reply

* Re: [BUG] branch renamed to 'HEAD'
From: Jacob Keller @ 2017-02-27 23:05 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, Karthik Nayak, Luc Van Oostenryck, Git List
In-Reply-To: <xmqq60jvnu9y.fsf@gitster.mtv.corp.google.com>

On Mon, Feb 27, 2017 at 2:28 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>
>> I guess something like the patch below works, but I wonder if there is a
>> less-horrible way to accomplish the same thing.
>
> I suspect that a less-horrible would be a lot more intrusive.  It
> would go like "interpret-branch-name only gives local branch name,
> and when it does not show it, the callers that know they do not
> necessarily need local branch name would call other at-mark things".
> As you pointed out with the @{upstream} that potentially point at a
> local branch, it will quickly get more involved, I would think, and
> I tend to think that this patch of yours is probably the least evil
> one among possible solutions.
>
> Perhaps with s/not_in_refs_heads/not_a_branch_name/ (or swapping
> polarity, "is_a_branch_name"), the resulting code may not be too
> hard to read?
>
> Thanks.

What about changing interpret-branch-name gains a flag to return a
fully qualified ref rather than returning just the name? That seems
like it would be more reasonable behavior.

Thanks,
Jake

^ permalink raw reply

* Re: [PATCH] strbuf: add strbuf_add_real_path()
From: René Scharfe @ 2017-02-27 22:45 UTC (permalink / raw)
  To: Brandon Williams; +Cc: Git List, Junio C Hamano, Jeff King
In-Reply-To: <20170227182217.GC153455@google.com>

Am 27.02.2017 um 19:22 schrieb Brandon Williams:
> On 02/25, René Scharfe wrote:
>> +void strbuf_add_real_path(struct strbuf *sb, const char *path)
>> +{
>> +	if (sb->len) {
>> +		struct strbuf resolved = STRBUF_INIT;
>> +		strbuf_realpath(&resolved, path, 1);
>> +		strbuf_addbuf(sb, &resolved);
>> +		strbuf_release(&resolved);
>> +	} else
>> +		strbuf_realpath(sb, path, 1);
>
> I know its not required but I would have braces on the 'else' branch
> since they were needed on the 'if' branch.  But that's up to you and
> your style :)

Personally I'd actually prefer them as well, but the project's style has 
traditionally been to avoid braces on such trailing single-line branches 
to save lines.  The CodingGuidelines for this topic have been clarified 
recently, though, and seem to require them now.  Interesting.

René

^ permalink raw reply

* Re: [BUG] branch renamed to 'HEAD'
From: Jeff King @ 2017-02-28  0:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jacob Keller, Karthik Nayak, Luc Van Oostenryck, Git List
In-Reply-To: <xmqqzih7kvbz.fsf@gitster.mtv.corp.google.com>

On Mon, Feb 27, 2017 at 04:33:36PM -0800, Junio C Hamano wrote:

> A flag to affect the behaviour (as opposed to &flag as a secondary
> return value, like Peff's patch does) can be made to work.  Perhaps
> a flag that says "keep the input as is if the result is not a local
> branch name" would pass an input "@" intact and that may be
> sufficient to allow "git branch -m @" to rename the current branch
> to "@" (I do not think it is a sensible rename, though ;-).  But
> probably some callers need to keep the original input and compare
> with the result to see if we expanded anything if we go that route.
> At that point, I am not sure if there are much differences in the
> ease of use between the two approaches.

I just went into more detail in my reply to Jacob, but I do think this
is a workable approach (and fortunately we seem to have banned bare "@"
as a name, along with anything containing "@{}", so I think we would end
up rejecting these nonsense names).

I'll see if I can work up a patch. We'll still need to pass the flag
around through the various functions, but at least it will be a flag and
not a confusing negated out-parameter.

-Peff

^ permalink raw reply

* [PATCH 1/2] wrapper.c: remove unused git_mkstemp() function
From: Ramsay Jones @ 2017-02-28  1:24 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, GIT Mailing-list


The last caller of git_mkstemp() was removed in commit 6fec0a89
("verify_signed_buffer: use tempfile object", 16-06-2016). Since
the introduction of the 'tempfile' APIs, along with git_mkstemp_mode,
it is unlikely that new callers will materialize. Remove the dead
code.

Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
---
 cache.h   |  3 ---
 wrapper.c | 17 -----------------
 2 files changed, 20 deletions(-)

diff --git a/cache.h b/cache.h
index 61fc86e6d..a575684a9 100644
--- a/cache.h
+++ b/cache.h
@@ -1045,9 +1045,6 @@ static inline int is_empty_tree_oid(const struct object_id *oid)
 	return !hashcmp(oid->hash, EMPTY_TREE_SHA1_BIN);
 }
 
-
-int git_mkstemp(char *path, size_t n, const char *template);
-
 /* set default permissions by passing mode arguments to open(2) */
 int git_mkstemps_mode(char *pattern, int suffix_len, int mode);
 int git_mkstemp_mode(char *pattern, int mode);
diff --git a/wrapper.c b/wrapper.c
index e7f197996..1a140639f 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -440,23 +440,6 @@ int xmkstemp(char *template)
 	return fd;
 }
 
-/* git_mkstemp() - create tmp file honoring TMPDIR variable */
-int git_mkstemp(char *path, size_t len, const char *template)
-{
-	const char *tmp;
-	size_t n;
-
-	tmp = getenv("TMPDIR");
-	if (!tmp)
-		tmp = "/tmp";
-	n = snprintf(path, len, "%s/%s", tmp, template);
-	if (len <= n) {
-		errno = ENAMETOOLONG;
-		return -1;
-	}
-	return mkstemp(path);
-}
-
 /* Adapted from libiberty's mkstemp.c. */
 
 #undef TMP_MAX
-- 
2.12.0

^ permalink raw reply related

* [PATCH 0/2] remove unused 'mkstemp(s)' code
From: Ramsay Jones @ 2017-02-28  1:22 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, GIT Mailing-list


I promised the first of these patches on 18th June last year! ;-)
(In response to Jeff's 'jk/gpg-interface-cleanup' branch).

Ramsay Jones (2):
  wrapper.c: remove unused git_mkstemp() function
  wrapper.c: remove unused gitmkstemps() function

 Makefile          |  5 -----
 cache.h           |  3 ---
 config.mak.uname  | 17 -----------------
 configure.ac      |  6 ------
 git-compat-util.h |  5 -----
 wrapper.c         | 24 ------------------------
 6 files changed, 60 deletions(-)

-- 
2.12.0

^ permalink raw reply

* [PATCH 2/2] wrapper.c: remove unused gitmkstemps() function
From: Ramsay Jones @ 2017-02-28  1:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: GIT Mailing-list


The last call to the mkstemps() function was removed in commit 659488326
("wrapper.c: delete dead function git_mkstemps()", 22-04-2016). In order
to support platforms without mkstemps(), this functionality was provided,
along with a Makefile build variable (NO_MKSTEMPS), by the gitmkstemps()
function. Remove the dead code, along with the defunct build machinery.

Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
---
 Makefile          |  5 -----
 config.mak.uname  | 17 -----------------
 configure.ac      |  6 ------
 git-compat-util.h |  5 -----
 wrapper.c         |  7 -------
 5 files changed, 40 deletions(-)

diff --git a/Makefile b/Makefile
index 8e4081e06..ca9f16d19 100644
--- a/Makefile
+++ b/Makefile
@@ -102,8 +102,6 @@ all::
 #
 # Define MKDIR_WO_TRAILING_SLASH if your mkdir() can't deal with trailing slash.
 #
-# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
-#
 # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
 # in the C library.
 #
@@ -1280,9 +1278,6 @@ ifdef MKDIR_WO_TRAILING_SLASH
 	COMPAT_CFLAGS += -DMKDIR_WO_TRAILING_SLASH
 	COMPAT_OBJS += compat/mkdir.o
 endif
-ifdef NO_MKSTEMPS
-	COMPAT_CFLAGS += -DNO_MKSTEMPS
-endif
 ifdef NO_UNSETENV
 	COMPAT_CFLAGS += -DNO_UNSETENV
 	COMPAT_OBJS += compat/unsetenv.o
diff --git a/config.mak.uname b/config.mak.uname
index 447f36ac2..7bdf86d2a 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -27,7 +27,6 @@ endif
 ifeq ($(uname_S),Linux)
 	HAVE_ALLOCA_H = YesPlease
 	NO_STRLCPY = YesPlease
-	NO_MKSTEMPS = YesPlease
 	HAVE_PATHS_H = YesPlease
 	LIBC_CONTAINS_LIBINTL = YesPlease
 	HAVE_DEV_TTY = YesPlease
@@ -41,7 +40,6 @@ endif
 ifeq ($(uname_S),GNU/kFreeBSD)
 	HAVE_ALLOCA_H = YesPlease
 	NO_STRLCPY = YesPlease
-	NO_MKSTEMPS = YesPlease
 	HAVE_PATHS_H = YesPlease
 	DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
 	LIBC_CONTAINS_LIBINTL = YesPlease
@@ -55,7 +53,6 @@ ifeq ($(uname_S),UnixWare)
 	SHELL_PATH = /usr/local/bin/bash
 	NO_IPV6 = YesPlease
 	NO_HSTRERROR = YesPlease
-	NO_MKSTEMPS = YesPlease
 	BASIC_CFLAGS += -Kthread
 	BASIC_CFLAGS += -I/usr/local/include
 	BASIC_LDFLAGS += -L/usr/local/lib
@@ -79,7 +76,6 @@ ifeq ($(uname_S),SCO_SV)
 	SHELL_PATH = /usr/bin/bash
 	NO_IPV6 = YesPlease
 	NO_HSTRERROR = YesPlease
-	NO_MKSTEMPS = YesPlease
 	BASIC_CFLAGS += -I/usr/local/include
 	BASIC_LDFLAGS += -L/usr/local/lib
 	NO_STRCASESTR = YesPlease
@@ -122,7 +118,6 @@ ifeq ($(uname_S),SunOS)
 	NO_STRCASESTR = YesPlease
 	NO_MEMMEM = YesPlease
 	NO_MKDTEMP = YesPlease
-	NO_MKSTEMPS = YesPlease
 	NO_REGEX = YesPlease
 	NO_MSGFMT_EXTENDED_OPTIONS = YesPlease
 	HAVE_DEV_TTY = YesPlease
@@ -168,7 +163,6 @@ ifeq ($(uname_O),Cygwin)
 		NO_D_TYPE_IN_DIRENT = YesPlease
 		NO_STRCASESTR = YesPlease
 		NO_MEMMEM = YesPlease
-		NO_MKSTEMPS = YesPlease
 		NO_SYMLINK_HEAD = YesPlease
 		NO_IPV6 = YesPlease
 		OLD_ICONV = UnfortunatelyYes
@@ -233,7 +227,6 @@ ifeq ($(uname_S),NetBSD)
 	BASIC_CFLAGS += -I/usr/pkg/include
 	BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
 	USE_ST_TIMESPEC = YesPlease
-	NO_MKSTEMPS = YesPlease
 	HAVE_PATHS_H = YesPlease
 	HAVE_BSD_SYSCTL = YesPlease
 endif
@@ -242,7 +235,6 @@ ifeq ($(uname_S),AIX)
 	NO_STRCASESTR = YesPlease
 	NO_MEMMEM = YesPlease
 	NO_MKDTEMP = YesPlease
-	NO_MKSTEMPS = YesPlease
 	NO_STRLCPY = YesPlease
 	NO_NSEC = YesPlease
 	FREAD_READS_DIRECTORIES = UnfortunatelyYes
@@ -263,7 +255,6 @@ ifeq ($(uname_S),GNU)
 	# GNU/Hurd
 	HAVE_ALLOCA_H = YesPlease
 	NO_STRLCPY = YesPlease
-	NO_MKSTEMPS = YesPlease
 	HAVE_PATHS_H = YesPlease
 	LIBC_CONTAINS_LIBINTL = YesPlease
 endif
@@ -272,7 +263,6 @@ ifeq ($(uname_S),IRIX)
 	NO_UNSETENV = YesPlease
 	NO_STRCASESTR = YesPlease
 	NO_MEMMEM = YesPlease
-	NO_MKSTEMPS = YesPlease
 	NO_MKDTEMP = YesPlease
 	# When compiled with the MIPSpro 7.4.4m compiler, and without pthreads
 	# (i.e. NO_PTHREADS is set), and _with_ MMAP (i.e. NO_MMAP is not set),
@@ -291,7 +281,6 @@ ifeq ($(uname_S),IRIX64)
 	NO_UNSETENV = YesPlease
 	NO_STRCASESTR = YesPlease
 	NO_MEMMEM = YesPlease
-	NO_MKSTEMPS = YesPlease
 	NO_MKDTEMP = YesPlease
 	# When compiled with the MIPSpro 7.4.4m compiler, and without pthreads
 	# (i.e. NO_PTHREADS is set), and _with_ MMAP (i.e. NO_MMAP is not set),
@@ -311,7 +300,6 @@ ifeq ($(uname_S),HP-UX)
 	NO_SETENV = YesPlease
 	NO_STRCASESTR = YesPlease
 	NO_MEMMEM = YesPlease
-	NO_MKSTEMPS = YesPlease
 	NO_STRLCPY = YesPlease
 	NO_MKDTEMP = YesPlease
 	NO_UNSETENV = YesPlease
@@ -352,7 +340,6 @@ ifeq ($(uname_S),Windows)
 	NO_ICONV = YesPlease
 	NO_STRTOUMAX = YesPlease
 	NO_MKDTEMP = YesPlease
-	NO_MKSTEMPS = YesPlease
 	SNPRINTF_RETURNS_BOGUS = YesPlease
 	NO_SVN_TESTS = YesPlease
 	RUNTIME_PREFIX = YesPlease
@@ -402,7 +389,6 @@ ifeq ($(uname_S),Interix)
 	NO_MKDTEMP = YesPlease
 	NO_STRTOUMAX = YesPlease
 	NO_NSEC = YesPlease
-	NO_MKSTEMPS = YesPlease
 	ifeq ($(uname_R),3.5)
 		NO_INET_NTOP = YesPlease
 		NO_INET_PTON = YesPlease
@@ -461,7 +447,6 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
 	NO_SETENV = YesPlease
 	NO_UNSETENV = YesPlease
 	NO_MKDTEMP = YesPlease
-	NO_MKSTEMPS = YesPlease
 	# Currently libiconv-1.9.1.
 	OLD_ICONV = UnfortunatelyYes
 	NO_REGEX = YesPlease
@@ -503,7 +488,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	NEEDS_LIBICONV = YesPlease
 	NO_STRTOUMAX = YesPlease
 	NO_MKDTEMP = YesPlease
-	NO_MKSTEMPS = YesPlease
 	NO_SVN_TESTS = YesPlease
 	NO_PERL_MAKEMAKER = YesPlease
 	RUNTIME_PREFIX = YesPlease
@@ -584,7 +568,6 @@ ifeq ($(uname_S),QNX)
 	NO_ICONV = YesPlease
 	NO_MEMMEM = YesPlease
 	NO_MKDTEMP = YesPlease
-	NO_MKSTEMPS = YesPlease
 	NO_NSEC = YesPlease
 	NO_PTHREADS = YesPlease
 	NO_R_TO_GCC_LINKER = YesPlease
diff --git a/configure.ac b/configure.ac
index 0b15f04b1..128165529 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1050,12 +1050,6 @@ GIT_CHECK_FUNC(mkdtemp,
 [NO_MKDTEMP=YesPlease])
 GIT_CONF_SUBST([NO_MKDTEMP])
 #
-# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
-GIT_CHECK_FUNC(mkstemps,
-[NO_MKSTEMPS=],
-[NO_MKSTEMPS=YesPlease])
-GIT_CONF_SUBST([NO_MKSTEMPS])
-#
 # Define NO_INITGROUPS if you don't have initgroups in the C library.
 GIT_CHECK_FUNC(initgroups,
 [NO_INITGROUPS=],
diff --git a/git-compat-util.h b/git-compat-util.h
index ef6d560e1..e626851fe 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -639,11 +639,6 @@ extern int gitsetenv(const char *, const char *, int);
 extern char *gitmkdtemp(char *);
 #endif
 
-#ifdef NO_MKSTEMPS
-#define mkstemps gitmkstemps
-extern int gitmkstemps(char *, int);
-#endif
-
 #ifdef NO_UNSETENV
 #define unsetenv gitunsetenv
 extern void gitunsetenv(const char *);
diff --git a/wrapper.c b/wrapper.c
index 1a140639f..0542fc758 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -514,13 +514,6 @@ int git_mkstemp_mode(char *pattern, int mode)
 	return git_mkstemps_mode(pattern, 0, mode);
 }
 
-#ifdef NO_MKSTEMPS
-int gitmkstemps(char *pattern, int suffix_len)
-{
-	return git_mkstemps_mode(pattern, suffix_len, 0600);
-}
-#endif
-
 int xmkstemp_mode(char *template, int mode)
 {
 	int fd;
-- 
2.12.0

^ permalink raw reply related

* [RFC] - url-safe base64 commit-id's
From: G. Sylvie Davies @ 2017-02-28  2:27 UTC (permalink / raw)
  To: Git Users

Is there any appetite for base64'd commit-id's, using the url-safe
variant (e.g. RFC 4648 [1] with padding removed)?

And so this:
712bad335dfa9c410a83f9873614a19726acb3a8

Becomes this:
cSutM136nEEKg_mHNhShlyass6g


Under the hood things cannot change (e.g., ".git/objects/71/") because
file systems are not always case sensitive.

But for "git log" and "git show" output it would be nice. And helps
with ambiguous commit id's too if you only want to specify a 7
character commit-id, since that encodes 42 bits instead of 28 bits.
I've run into problems with maximum command length on windows (32767
chars) because I was specifying so many commit-ids on the command-line
that I blew past that limit. This would help there, too.

Might be particularly helpful with the transition to a new hash.
e.g., a 43 character Base64 id instead of a 64 character hex id.


- Sylvie

[1] - https://tools.ietf.org/html/rfc4648#page-7

^ permalink raw reply

* What's cooking in git.git (Feb 2017, #09; Mon, 27)
From: Junio C Hamano @ 2017-02-27 23:41 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 ones marked with '.' do not appear in any of
the integration branches, but I am still holding onto them.

The first batch post 2.12 is rather a big one (and intentionally
so).  Among the notable is that major part of "rebase -i" is now
driven by the sequencer backend (Thanks, Dscho), and the API
implementations of attribute subsystem and ref subsystem have also
been cleaned up (Thanks, Brandon & Michael).

The tip of 'next' has been rewound.

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"]

* bc/blame-doc-fix (2017-02-22) 1 commit
  (merged to 'next' on 2017-02-22 at 81c0ff2283)
 + Documentation: use brackets for optional arguments

 Doc update.


* bc/worktree-doc-fix-detached (2017-02-22) 1 commit
  (merged to 'next' on 2017-02-22 at 8257025363)
 + Documentation: correctly spell git worktree --detach

 Doc update.


* bw/attr (2017-02-01) 27 commits
  (merged to 'next' on 2017-02-14 at d35c1d7e4a)
 + attr: reformat git_attr_set_direction() function
 + attr: push the bare repo check into read_attr()
 + attr: store attribute stack in attr_check structure
 + attr: tighten const correctness with git_attr and match_attr
 + attr: remove maybe-real, maybe-macro from git_attr
 + attr: eliminate global check_all_attr array
 + attr: use hashmap for attribute dictionary
 + attr: change validity check for attribute names to use positive logic
 + attr: pass struct attr_check to collect_some_attrs
 + attr: retire git_check_attrs() API
 + attr: convert git_check_attrs() callers to use the new API
 + attr: convert git_all_attrs() to use "struct attr_check"
 + attr: (re)introduce git_check_attr() and struct attr_check
 + attr: rename function and struct related to checking attributes
 + attr.c: outline the future plans by heavily commenting
 + Documentation: fix a typo
 + attr.c: add push_stack() helper
 + attr: support quoting pathname patterns in C style
 + attr.c: plug small leak in parse_attr_line()
 + attr.c: tighten constness around "git_attr" structure
 + attr.c: simplify macroexpand_one()
 + attr.c: mark where #if DEBUG ends more clearly
 + attr.c: complete a sentence in a comment
 + attr.c: explain the lack of attr-name syntax check in parse_attr()
 + attr.c: update a stale comment on "struct match_attr"
 + attr.c: use strchrnul() to scan for one line
 + commit.c: use strchrnul() to scan for one line

 The gitattributes machinery is being taught to work better in a
 multi-threaded environment.


* cw/tag-reflog-message (2017-02-08) 1 commit
  (merged to 'next' on 2017-02-10 at 3968b3a58b)
 + tag: generate useful reflog message

 "git tag" did not leave useful message when adding a new entry to
 reflog; this was left unnoticed for a long time because refs/tags/*
 doesn't keep reflog by default.


* dr/doc-check-ref-format-normalize (2017-02-21) 1 commit
  (merged to 'next' on 2017-02-21 at 5e88b7a93d)
 + git-check-ref-format: clarify documentation for --normalize

 Doc update.


* dt/gc-ignore-old-gc-logs (2017-02-13) 1 commit
  (merged to 'next' on 2017-02-16 at 8f48e1b405)
 + gc: ignore old gc.log files

 A "gc.log" file left by a backgrounded "gc --auto" disables further
 automatic gc; it has been taught to run at least once a day (by
 default) by ignoring a stale "gc.log" file that is too old.


* gp/document-dotfiles-in-templates-are-not-copied (2017-02-17) 1 commit
  (merged to 'next' on 2017-02-21 at bbfa2bb7d4)
 + init: document dotfiles exclusion on template copy

 Doc update.


* jh/preload-index-skip-skip (2017-02-10) 1 commit
  (merged to 'next' on 2017-02-16 at 39077062f9)
 + preload-index: avoid lstat for skip-worktree items

 The preload-index code has been taught not to bother with the index
 entries that are paths that are not checked out by "sparse checkout".


* jk/alternate-ref-optim (2017-02-08) 11 commits
  (merged to 'next' on 2017-02-10 at f26f32cff6)
 + receive-pack: avoid duplicates between our refs and alternates
 + receive-pack: treat namespace .have lines like alternates
 + receive-pack: fix misleading namespace/.have comment
 + receive-pack: use oidset to de-duplicate .have lines
 + add oidset API
 + fetch-pack: cache results of for_each_alternate_ref
 + for_each_alternate_ref: replace transport code with for-each-ref
 + for_each_alternate_ref: pass name/oid instead of ref struct
 + for_each_alternate_ref: use strbuf for path allocation
 + for_each_alternate_ref: stop trimming trailing slashes
 + for_each_alternate_ref: handle failure from real_pathdup()

 Optimizes resource usage while enumerating refs from alternate
 object store, to help receiving end of "push" that hosts a
 repository with many "forks".


* jk/delta-chain-limit (2017-01-27) 2 commits
  (merged to 'next' on 2017-02-06 at 9ff36ae9b2)
 + pack-objects: convert recursion to iteration in break_delta_chain()
 + pack-objects: enforce --depth limit in reused deltas

 "git repack --depth=<n>" for a long time busted the specified depth
 when reusing delta from existing packs.  This has been corrected.


* jk/describe-omit-some-refs (2017-01-23) 5 commits
  (merged to 'next' on 2017-01-23 at f8a14b4996)
 + describe: teach describe negative pattern matches
 + describe: teach --match to accept multiple patterns
 + name-rev: add support to exclude refs by pattern match
 + name-rev: extend --refs to accept multiple patterns
 + doc: add documentation for OPT_STRING_LIST

 "git describe" and "git name-rev" have been taught to take more
 than one refname patterns to restrict the set of refs to base their
 naming output on, and also learned to take negative patterns to
 name refs not to be used for naming via their "--exclude" option.


* jk/grep-no-index-fix (2017-02-14) 7 commits
  (merged to 'next' on 2017-02-16 at c84c927fa8)
 + grep: treat revs the same for --untracked as for --no-index
 + grep: do not diagnose misspelt revs with --no-index
 + grep: avoid resolving revision names in --no-index case
 + grep: fix "--" rev/pathspec disambiguation
 + grep: re-order rev-parsing loop
 + grep: do not unnecessarily query repo for "--"
 + grep: move thread initialization a little lower

 The code to parse the command line "git grep <patterns>... <rev>
 [[--] <pathspec>...]" has been cleaned up, and a handful of bugs
 have been fixed (e.g. we used to check "--" if it is a rev).


* jk/show-branch-lift-name-len-limit (2017-02-15) 3 commits
  (merged to 'next' on 2017-02-16 at 40d22f5f34)
 + show-branch: use skip_prefix to drop magic numbers
 + show-branch: store resolved head in heap buffer
 + show-branch: drop head_len variable

 "git show-branch" expected there were only very short branch names
 in the repository and used a fixed-length buffer to hold them
 without checking for overflow.


* jk/tempfile-ferror-fclose-confusion (2017-02-17) 1 commit
  (merged to 'next' on 2017-02-21 at 479ba0131f)
 + tempfile: set errno to a known value before calling ferror()

 A caller of tempfile API that uses stdio interface to write to
 files may ignore errors while writing, which is detected when
 tempfile is closed (with a call to ferror()).  By that time, the
 original errno that may have told us what went wrong is likely to
 be long gone and was overwritten by an irrelevant value.
 close_tempfile() now resets errno to EIO to make errno at least
 predictable.


* jn/remote-helpers-with-git-dir (2017-02-14) 2 commits
  (merged to 'next' on 2017-02-16 at c093c543c4)
 + remote helpers: avoid blind fall-back to ".git" when setting GIT_DIR
 + remote: avoid reading $GIT_DIR config in non-repo

 "git ls-remote" and "git archive --remote" are designed to work
 without being in a directory under Git's control.  However, recent
 updates revealed that we randomly look into a directory called
 .git/ without actually doing necessary set-up when working in a
 repository.  Stop doing so.


* js/git-path-in-subdir (2017-02-17) 2 commits
  (merged to 'next' on 2017-02-17 at b3c3b2dce6)
 + rev-parse: fix several options when running in a subdirectory
 + rev-parse tests: add tests executed from a subdirectory

 The "--git-path", "--git-common-dir", and "--shared-index-path"
 options of "git rev-parse" did not produce usable output.  They are
 now updated to show the path to the correct file, relative to where
 the caller is.


* js/rebase-helper (2017-02-09) 2 commits
  (merged to 'next' on 2017-02-14 at ae2474048e)
 + rebase -i: use the rebase--helper builtin
 + rebase--helper: add a builtin helper for interactive rebases

 "git rebase -i" starts using the recently updated "sequencer" code.


* km/delete-ref-reflog-message (2017-02-20) 4 commits
  (merged to 'next' on 2017-02-21 at 4ee4ce3f64)
 + branch: record creation of renamed branch in HEAD's log
 + rename_ref: replace empty message in HEAD's log
 + update-ref: pass reflog message to delete_ref()
 + delete_ref: accept a reflog message argument

 "git update-ref -d" and other operations to delete references did
 not leave any entry in HEAD's reflog when the reference being
 deleted was the current branch.  This is not a problem in practice
 because you do not want to delete the branch you are currently on,
 but caused renaming of the current branch to something else not to
 be logged in a useful way.


* kn/ref-filter-branch-list (2017-02-07) 21 commits
  (merged to 'next' on 2017-02-10 at 794bb8284d)
 + ref-filter: resurrect "strip" as a synonym to "lstrip"
  (merged to 'next' on 2017-01-31 at e7592a5461)
 + branch: implement '--format' option
 + branch: use ref-filter printing APIs
 + branch, tag: use porcelain output
 + ref-filter: allow porcelain to translate messages in the output
 + ref-filter: add an 'rstrip=<N>' option to atoms which deal with refnames
 + ref-filter: modify the 'lstrip=<N>' option to work with negative '<N>'
 + ref-filter: Do not abruptly die when using the 'lstrip=<N>' option
 + ref-filter: rename the 'strip' option to 'lstrip'
 + ref-filter: make remote_ref_atom_parser() use refname_atom_parser_internal()
 + ref-filter: introduce refname_atom_parser()
 + ref-filter: introduce refname_atom_parser_internal()
 + ref-filter: make "%(symref)" atom work with the ':short' modifier
 + ref-filter: add support for %(upstream:track,nobracket)
 + ref-filter: make %(upstream:track) prints "[gone]" for invalid upstreams
 + ref-filter: introduce format_ref_array_item()
 + ref-filter: move get_head_description() from branch.c
 + ref-filter: modify "%(objectname:short)" to take length
 + ref-filter: implement %(if:equals=<string>) and %(if:notequals=<string>)
 + ref-filter: include reference to 'used_atom' within 'atom_value'
 + ref-filter: implement %(if), %(then), and %(else) atoms

 The code to list branches in "git branch" has been consolidated
 with the more generic ref-filter API.


* lt/pathspec-negative (2017-02-10) 2 commits
  (merged to 'next' on 2017-02-10 at 8ea7874076)
 + pathspec: don't error out on all-exclusionary pathspec patterns
 + pathspec magic: add '^' as alias for '!'

 The "negative" pathspec feature was somewhat more cumbersome to use
 than necessary in that its short-hand used "!" which needed to be
 escaped from shells, and it required "exclude from what?" specified.


* mh/ref-remove-empty-directory (2017-01-07) 23 commits
  (merged to 'next' on 2017-02-10 at bcfd359e95)
 + files_transaction_commit(): clean up empty directories
 + try_remove_empty_parents(): teach to remove parents of reflogs, too
 + try_remove_empty_parents(): don't trash argument contents
 + try_remove_empty_parents(): rename parameter "name" -> "refname"
 + delete_ref_loose(): inline function
 + delete_ref_loose(): derive loose reference path from lock
 + log_ref_write_1(): inline function
 + log_ref_setup(): manage the name of the reflog file internally
 + log_ref_write_1(): don't depend on logfile argument
 + log_ref_setup(): pass the open file descriptor back to the caller
 + log_ref_setup(): improve robustness against races
 + log_ref_setup(): separate code for create vs non-create
 + log_ref_write(): inline function
 + rename_tmp_log(): improve error reporting
 + rename_tmp_log(): use raceproof_create_file()
 + lock_ref_sha1_basic(): use raceproof_create_file()
 + lock_ref_sha1_basic(): inline constant
 + raceproof_create_file(): new function
 + safe_create_leading_directories(): set errno on SCLD_EXISTS
 + safe_create_leading_directories_const(): preserve errno
 + t5505: use "for-each-ref" to test for the non-existence of references
 + refname_is_safe(): correct docstring
 + files_rename_ref(): tidy up whitespace
 (this branch is used by nd/files-backend-git-dir, nd/prune-in-worktree and nd/worktree-kill-parse-ref.)

 Deletion of a branch "foo/bar" could remove .git/refs/heads/foo
 once there no longer is any other branch whose name begins with
 "foo/", but we didn't do so so far.  Now we do.


* mh/submodule-hash (2017-02-13) 9 commits
  (merged to 'next' on 2017-02-14 at 43f2dcbe29)
 + read_loose_refs(): read refs using resolve_ref_recursively()
 + files_ref_store::submodule: use NULL for the main repository
 + base_ref_store_init(): remove submodule argument
 + refs: push the submodule attribute down
 + refs: store submodule ref stores in a hashmap
 + register_ref_store(): new function
 + refs: remove some unnecessary handling of submodule == ""
 + refs: make some ref_store lookup functions private
 + refs: reorder some function definitions
 (this branch is used by nd/files-backend-git-dir, nd/prune-in-worktree and nd/worktree-kill-parse-ref.)

 Code and design clean-up for the refs API.


* mm/merge-rename-delete-message (2017-01-30) 1 commit
  (merged to 'next' on 2017-02-10 at 8bf8146029)
 + merge-recursive: make "CONFLICT (rename/delete)" message show both paths

 When "git merge" detects a path that is renamed in one history
 while the other history deleted (or modified) it, it now reports
 both paths to help the user understand what is going on in the two
 histories being merged.


* mm/two-more-xstrfmt (2017-02-16) 2 commits
  (merged to 'next' on 2017-02-17 at 2454ee9847)
 + bisect_next_all: convert xsnprintf to xstrfmt
 + stop_progress_msg: convert xsnprintf to xstrfmt

 Code clean-up and a string truncation fix.


* nd/clean-preserve-errno-in-warning (2017-02-16) 1 commit
  (merged to 'next' on 2017-02-16 at c0802f7627)
 + clean: use warning_errno() when appropriate

 Some warning() messages from "git clean" were updated to show the
 errno from failed system calls.


* ps/doc-gc-aggressive-depth-update (2017-02-24) 1 commit
  (merged to 'next' on 2017-02-24 at f023322bbb)
 + docs/git-gc: fix default value for `--aggressiveDepth`

 Doc update.


* ps/urlmatch-wildcard (2017-02-01) 5 commits
  (merged to 'next' on 2017-02-10 at 2ed9ea48ee)
 + urlmatch: allow globbing for the URL host part
 + urlmatch: include host in urlmatch ranking
 + urlmatch: split host and port fields in `struct url_info`
 + urlmatch: enable normalization of URLs with globs
 + mailmap: add Patrick Steinhardt's work address

 The <url> part in "http.<url>.<variable>" configuration variable
 can now be spelled with '*' that serves as wildcard.
 E.g. "http.https://*.example.com.proxy" can be used to specify the
 proxy used for https://a.example.com, https://b.example.com, etc.,
 i.e. any host in the example.com domain.


* rl/remote-allow-missing-branch-name-merge (2017-02-21) 1 commit
  (merged to 'next' on 2017-02-22 at cbe923c8da)
 + remote: ignore failure to remove missing branch.<name>.merge

 "git remote rm X", when a branch has remote X configured as the
 value of its branch.*.remote, tried to remove branch.*.remote and
 branch.*.merge and failed if either is unset.


* rt/align-add-i-help-text (2017-02-22) 1 commit
  (merged to 'next' on 2017-02-22 at a8573afb9a)
 + git add -i: replace \t with blanks in the help message

 Doc update.


* sf/putty-w-args (2017-02-10) 5 commits
  (merged to 'next' on 2017-02-14 at 7f157e7020)
 + connect.c: stop conflating ssh command names and overrides
 + connect: Add the envvar GIT_SSH_VARIANT and ssh.variant config
 + git_connect(): factor out SSH variant handling
 + connect: rename tortoiseplink and putty variables
 + connect: handle putty/plink also in GIT_SSH_COMMAND

 The command line options for ssh invocation needs to be tweaked for
 some implementations of SSH (e.g. PuTTY plink wants "-P <port>"
 while OpenSSH wants "-p <port>" to specify port to connect to), and
 the variant was guessed when GIT_SSH environment variable is used
 to specify it.  The logic to guess now applies to the command
 specified by the newer GIT_SSH_COMMAND and also core.sshcommand
 configuration variable, and comes with an escape hatch for users to
 deal with misdetected cases.


* sg/completion (2017-02-13) 22 commits
  (merged to 'next' on 2017-02-13 at 118c192874)
 + completion: restore removed line continuating backslash
  (merged to 'next' on 2017-02-10 at 55b2785d89)
 + completion: cache the path to the repository
 + completion: extract repository discovery from __gitdir()
 + completion: don't guard git executions with __gitdir()
 + completion: consolidate silencing errors from git commands
 + completion: don't use __gitdir() for git commands
 + completion: respect 'git -C <path>'
 + rev-parse: add '--absolute-git-dir' option
 + completion: fix completion after 'git -C <path>'
 + completion: don't offer commands when 'git --opt' needs an argument
 + completion: list short refs from a remote given as a URL
 + completion: don't list 'HEAD' when trying refs completion outside of a repo
 + completion: list refs from remote when remote's name matches a directory
 + completion: respect 'git --git-dir=<path>' when listing remote refs
 + completion: fix most spots not respecting 'git --git-dir=<path>'
 + completion: ensure that the repository path given on the command line exists
 + completion tests: add tests for the __git_refs() helper function
 + completion tests: check __gitdir()'s output in the error cases
 + completion tests: consolidate getting path of current working directory
 + completion tests: make the $cur variable local to the test helper functions
 + completion tests: don't add test cruft to the test repository
 + completion: improve __git_refs()'s in-code documentation
 (this branch is used by sg/completion-refs-speedup.)

 Clean-up and updates to command line completion (in contrib/).


* vn/xdiff-func-context (2017-01-15) 1 commit
  (merged to 'next' on 2017-02-21 at 838eab8d93)
 + xdiff -W: relax end-of-file function detection

 "git diff -W" has been taught to handle the case where a new
 function is added at the end of the file better.

--------------------------------------------------
[New Topics]

* dp/filter-branch-prune-empty (2017-02-23) 4 commits
 - p7000: add test for filter-branch with --prune-empty
 - filter-branch: fix --prune-empty on parentless commits
 - t7003: ensure --prune-empty removes entire branch when applicable
 - t7003: ensure --prune-empty can prune root commit

 "git filter-branch --prune-empty" drops a single-parent commit that
 becomes a no-op, but did not drop a root commit whose tree is empty.

 Needs review.


* jc/config-case-cmdline-take-2 (2017-02-23) 2 commits
 - config: use git_config_parse_key() in git_config_parse_parameter()
 - config: move a few helper functions up

 The code to parse "git -c VAR=VAL cmd" and set configuration
 variable for the duration of cmd had two small bugs, which have
 been fixed.

 Will merge to 'next'.
 This supersedes jc/config-case-cmdline topic that has been discarded.


* ab/cond-skip-tests (2017-02-27) 2 commits
 - gitweb tests: skip tests when we don't have Time::HiRes
 - cvs tests: skip tests that call "cvs commit" when running as root

 A few tests were run conditionally under (rare) conditions where
 they cannot be run (like running cvs tests under 'root' account).


* jk/auto-namelen-in-interpret-branch-name (2017-02-27) 1 commit
 - interpret_branch_name(): handle auto-namelen for @{-1}

 A small bug in the code that parses @{...} has been fixed.

 Will merge to 'next'.


* jk/interop-test (2017-02-27) 2 commits
 - t/interop: add test of old clients against modern git-daemon
 - t: add an interoperability test harness

 Picking two versions of Git and running tests to make sure the
 older one and the newer one interoperate happily has now become
 possible.

 Needs review.


* jk/parse-config-key-cleanup (2017-02-24) 3 commits
 - parse_hide_refs_config: tell parse_config_key we don't want a subsection
 - parse_config_key: allow matching single-level config
 - parse_config_key: use skip_prefix instead of starts_with
 (this branch uses sb/parse-hide-refs-config-cleanup.)

 The "parse_config_key()" API function has been cleaned up.

 Will merge to 'next'.


* jk/t6300-cleanup (2017-02-27) 1 commit
 - t6300: avoid creating refs/heads/HEAD

 A test that creats a confusing branch whose name is HEAD when any
 branch name would have sufficed has been corrected.

 Will merge to 'next'.


* rs/commit-parsing-optim (2017-02-27) 2 commits
 - commit: don't check for space twice when looking for header
 - commit: be more precise when searching for headers

 The code that parses header fields in the commit object has been
 updated for (micro)performance and code hygiene.

 Will merge to 'next'.


* rs/sha1-file-plug-fallback-base-leak (2017-02-27) 1 commit
 - sha1_file: release fallback base's memory in unpack_entry()

 A leak in a codepath to read from a packed object in (rare) cases
 has been plugged.

 Will merge to 'next'.


* rs/strbuf-add-real-path (2017-02-27) 2 commits
 - strbuf: add strbuf_add_real_path()
 - cocci: use ALLOC_ARRAY

 An helper function to make it easier to append the result from
 real_path() to a strbuf has been added.

 Will merge to 'next'.


* sb/parse-hide-refs-config-cleanup (2017-02-24) 1 commit
 - refs: parse_hide_refs_config to use parse_config_key
 (this branch is used by jk/parse-config-key-cleanup.)

 Code clean-up.

 Will merge to 'next'.


* sg/clone-refspec-from-command-line-config (2017-02-27) 1 commit
 - clone: respect configured fetch respecs during initial fetch

 Needs review.
 cf. <20170227211217.73gydlxb2qu2sp3m@sigill.intra.peff.net>


* sk/dash-is-previous (2017-02-27) 6 commits
 - revert.c: delegate handling of "-" shorthand to setup_revisions
 - merge.c: delegate handling of "-" shorthand to revision.c:get_sha1
 - sha1_name.c: teach get_sha1_1 "-" shorthand for "@{-1}"
 - revision.c: args starting with "-" might be a revision
 - revision.c: swap if/else blocks
 - revision.c: do not update argv with unknown option

 A dash "-" can be written to mean "the branch that was previously
 checked out" in more places.

 Needs review.
 cf. <1488007487-12965-1-git-send-email-kannan.siddharth12@gmail.com> 

--------------------------------------------------
[Stalled]

* nd/worktree-move (2017-01-27) 7 commits
 . fixup! worktree move: new command
 . worktree remove: new command
 . worktree move: refuse to move worktrees with submodules
 . worktree move: accept destination as directory
 . worktree move: new command
 . worktree.c: add update_worktree_location()
 . worktree.c: add validate_worktree()

 "git worktree" learned move and remove subcommands.

 Tentatively ejected as it seems to break 'pu' when merged.


* cc/split-index-config (2016-12-26) 21 commits
 - Documentation/git-update-index: explain splitIndex.*
 - Documentation/config: add splitIndex.sharedIndexExpire
 - read-cache: use freshen_shared_index() in read_index_from()
 - read-cache: refactor read_index_from()
 - t1700: test shared index file expiration
 - read-cache: unlink old sharedindex files
 - config: add git_config_get_expiry() from gc.c
 - read-cache: touch shared index files when used
 - sha1_file: make check_and_freshen_file() non static
 - Documentation/config: add splitIndex.maxPercentChange
 - t1700: add tests for splitIndex.maxPercentChange
 - read-cache: regenerate shared index if necessary
 - config: add git_config_get_max_percent_split_change()
 - Documentation/git-update-index: talk about core.splitIndex config var
 - Documentation/config: add information for core.splitIndex
 - t1700: add tests for core.splitIndex
 - update-index: warn in case of split-index incoherency
 - read-cache: add and then use tweak_split_index()
 - split-index: add {add,remove}_split_index() functions
 - config: add git_config_get_split_index()
 - config: mark an error message up for translation

 The experimental "split index" feature has gained a few
 configuration variables to make it easier to use.

 Expecting a reroll.
 cf. <20161226102222.17150-1-chriscool@tuxfamily.org>
 cf. <a1a44640-ff6c-2294-72ac-46322eff8505@ramsayjones.plus.com>
 cf. <CAP8UFD3_1EN=0EsD12Cew1MuW8yhtPAZw0M_g3wmvKFk-uGXxw@mail.gmail.com>
 cf. <CAP8UFD1wmbR_rHyqn0q=0hw6-hHYFTzr=3yxS2XS9qTdY1kWFA@mail.gmail.com>
 cf. <xmqqbmunq6mg.fsf@gitster.mtv.corp.google.com>
 cf. <CAP8UFD0bgxVrc=RGHs1GrZ_5PF4cdfhqXLMiCSJTNw9axrr=_w@mail.gmail.com>


* pb/bisect (2017-02-18) 28 commits
 - fixup! bisect--helper: `bisect_next_check` & bisect_voc shell function in C
 - bisect--helper: remove the dequote in bisect_start()
 - bisect--helper: retire `--bisect-auto-next` subcommand
 - bisect--helper: retire `--bisect-autostart` subcommand
 - bisect--helper: retire `--bisect-write` subcommand
 - bisect--helper: `bisect_replay` shell function in C
 - bisect--helper: `bisect_log` shell function in C
 - bisect--helper: retire `--write-terms` subcommand
 - bisect--helper: retire `--check-expected-revs` subcommand
 - bisect--helper: `bisect_state` & `bisect_head` shell function in C
 - bisect--helper: `bisect_autostart` shell function in C
 - bisect--helper: retire `--next-all` subcommand
 - bisect--helper: retire `--bisect-clean-state` subcommand
 - bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C
 - t6030: no cleanup with bad merge base
 - bisect--helper: `bisect_start` shell function partially in C
 - bisect--helper: `get_terms` & `bisect_terms` shell function in C
 - bisect--helper: `bisect_next_check` & bisect_voc shell function in C
 - bisect--helper: `check_and_set_terms` shell function in C
 - bisect--helper: `bisect_write` shell function in C
 - bisect--helper: `is_expected_rev` & `check_expected_revs` shell function in C
 - bisect--helper: `bisect_reset` shell function in C
 - wrapper: move is_empty_file() and rename it as is_empty_or_missing_file()
 - t6030: explicitly test for bisection cleanup
 - bisect--helper: `bisect_clean_state` shell function in C
 - bisect--helper: `write_terms` shell function in C
 - bisect: rewrite `check_term_format` shell function in C
 - bisect--helper: use OPT_CMDMODE instead of OPT_BOOL

 Move more parts of "git bisect" to C.

 Expecting a reroll.
 cf. <CAFZEwPPXPPHi8KiEGS9ggzNHDCGhuqMgH9Z8-Pf9GLshg8+LPA@mail.gmail.com>
 cf. <CAFZEwPM9RSTGN54dzaw9gO9iZmsYjJ_d1SjUD4EzSDDbmh-XuA@mail.gmail.com>
 cf. <CAFZEwPNUXcNY9Qdz=_B7q2kQuaecPzJtTMGdv8YMUPEz2vnp8A@mail.gmail.com>


* ls/filter-process-delayed (2017-01-08) 1 commit
 . convert: add "status=delayed" to filter process protocol

 Ejected, as does not build when merged to 'pu'.


* sh/grep-tree-obj-tweak-output (2017-01-20) 2 commits
 - grep: use '/' delimiter for paths
 - grep: only add delimiter if there isn't one already

 "git grep", when fed a tree-ish as an input, shows each hit
 prefixed with "<tree-ish>:<path>:<lineno>:".  As <tree-ish> is
 almost always either a commit or a tag that points at a commit, the
 early part of the output "<tree-ish>:<path>" can be used as the
 name of the blob and given to "git show".  When <tree-ish> is a
 tree given in the extended SHA-1 syntax (e.g. "<commit>:", or
 "<commit>:<dir>"), however, this results in a string that does not
 name a blob (e.g. "<commit>::<path>" or "<commit>:<dir>:<path>").
 "git grep" has been taught to be a bit more intelligent about these
 cases and omit a colon (in the former case) or use slash (in the
 latter case) to produce "<commit>:<path>" and
 "<commit>:<dir>/<path>" that can be used as the name of a blob.

 Expecting a reroll?  Is this good enough with known limitations?


* jc/diff-b-m (2015-02-23) 5 commits
 . WIPWIP
 . WIP: diff-b-m
 - diffcore-rename: allow easier debugging
 - diffcore-rename.c: add locate_rename_src()
 - diffcore-break: allow debugging

 "git diff -B -M" produced incorrect patch when the postimage of a
 completely rewritten file is similar to the preimage of a removed
 file; such a resulting file must not be expressed as a rename from
 other place.

 The fix in this patch is broken, unfortunately.

 Will discard.

--------------------------------------------------
[Cooking]

* jh/send-email-one-cc (2017-02-27) 1 commit
 - send-email: only allow one address per body tag

 "Cc:" on the trailer part does not have to conform to RFC strictly,
 unlike in the e-mail header.  "git send-email" has been updated to
 ignore anything after '>' when picking addresses, to allow non-address
 cruft like " # stable 4.4" after the address.

 Will merge to 'next'.


* jk/http-auth (2017-02-27) 2 commits
 - http: add an "auto" mode for http.emptyauth
 - http: restrict auth methods to what the server advertises

 Reduce authentication round-trip over HTTP when the server supports
 just a single authentication method.

 Will merge to 'next'.


* jk/ident-empty (2017-02-23) 4 commits
 - ident: do not ignore empty config name/email
 - ident: reject all-crud ident name
 - ident: handle NULL email when complaining of empty name
 - ident: mark error messages for translation

 user.email that consists of only cruft chars should have
 consistently errored out, but didn't.

 Will merge to 'next'.


* jt/upload-pack-error-report (2017-02-23) 1 commit
 - upload-pack: report "not our ref" to client

 "git upload-pack", which is a counter-part of "git fetch", did not
 report a request for a ref that was not advertised as invalid.
 This is generally not a problem (because "git fetch" will stop
 before making such a request), but is the right thing to do.

 Will merge to 'next'.


* ah/doc-ls-files-quotepath (2017-02-22) 1 commit
 - Documentation: clarify core.quotePath and update git-ls-files doc

 Documentation for "git ls-files" did not refer to core.quotePath

 Reroll exists but not picked up yet.


* jh/memihash-opt (2017-02-17) 5 commits
 - name-hash: remember previous dir_entry during lazy_init_name_hash
 - name-hash: specify initial size for istate.dir_hash table
 - name-hash: precompute hash values during preload-index
 - hashmap: allow memihash computation to be continued
 - name-hash: eliminate duplicate memihash call

 Expecting an update for perf?


* nd/prune-in-worktree (2017-02-19) 15 commits
 . rev-list: expose and document --single-worktree
 . revision.c: --reflog add HEAD reflog from all worktrees
 . files-backend: make reflog iterator go through per-worktree reflog
 . refs: add refs_for_each_reflog[_ent]()
 . revision.c: --all adds HEAD from all worktrees
 . refs: remove dead for_each_*_submodule()
 . revision.c: use refs_for_each*() instead of for_each_*_submodule()
 . refs: add a refs_for_each_in() and friends
 . refs: add refs_for_each_ref()
 . refs: add refs_head_ref()
 . refs: add refs_read_ref[_full]()
 . refs: move submodule slash stripping code to get_submodule_ref_store
 . revision.c: --indexed-objects add objects from all worktrees
 . revision.c: refactor add_index_objects_to_pending()
 . revision.h: new flag in struct rev_info wrt. worktree-related refs
 (this branch uses nd/worktree-kill-parse-ref; is tangled with nd/files-backend-git-dir.)

 "git gc" and friends when multiple worktrees are used off of a
 single repository did not consider the index and per-worktree refs
 of other worktrees as the root for reachability traversal, making
 objects that are in use only in other worktrees to be subject to
 garbage collection.


* mm/fetch-show-error-message-on-unadvertised-object (2017-02-22) 4 commits
 - fetch-pack: add specific error for fetching an unadvertised object
 - fetch_refs_via_pack: call report_unmatched_refs
 - squash??? remove unfinished sentence
 - fetch-pack: move code to report unmatched refs to a function

 "git fetch" that requests a commit by object name, when the other
 side does not allow such an request, failed without much
 explanation.

 Will squash the change in before merging to 'next'.


* nd/worktree-kill-parse-ref (2017-02-19) 22 commits
 . refs: kill set_worktree_head_symref()
 . refs: add refs_create_symref()
 . worktree.c: kill parse_ref() in favor of refs_resolve_ref_unsafe()
 . refs.c: add refs_resolve_ref_unsafe()
 . refs: introduce get_worktree_ref_store()
 . refs: rename get_ref_store() to get_submodule_ref_store() and make it public
 . files-backend: remove submodule_allowed from files_downcast()
 . refs: move submodule code out of files-backend.c
 . path.c: move some code out of strbuf_git_path_submodule()
 . refs.c: make get_main_ref_store() public and use it
 . refs.c: kill register_ref_store(), add register_submodule_ref_store()
 . refs.c: flatten get_ref_store() a bit
 . refs: rename lookup_ref_store() to lookup_submodule_ref_store()
 . refs.c: introduce get_main_ref_store()
 . files-backend: remove the use of git_path()
 . refs.c: share is_per_worktree_ref() to files-backend.c
 . files-backend: replace *git_path*() with files_path()
 . files-backend: add files_path()
 . files-backend: convert git_path() to strbuf_git_path()
 . refs-internal.c: make files_log_ref_write() static
 . Merge branch 'mh/ref-remove-empty-directory' into nd/files-backend-git-dir
 . Merge branch 'mh/submodule-hash' into nd/files-backend-git-dir
 (this branch is used by nd/prune-in-worktree; is tangled with nd/files-backend-git-dir.)

 (hopefully) a beginning of safer "git worktree" that is resistant
 to "gc".

 Waiting for nd/files-backend-git-dir to settle.


* nd/files-backend-git-dir (2017-02-22) 26 commits
 . t1406: new tests for submodule ref store
 . t1405: some basic tests on main ref store
 . t/helper: add test-ref-store to test ref-store functions
 . refs: delete pack_refs() in favor of refs_pack_refs()
 . files-backend: avoid ref api targetting main ref store
 . refs: new transaction related ref-store api
 . refs: add new ref-store api
 . refs: rename get_ref_store() to get_submodule_ref_store() and make it public
 . files-backend: replace submodule_allowed check in files_downcast()
 . refs: move submodule code out of files-backend.c
 . path.c: move some code out of strbuf_git_path_submodule()
 . refs.c: make get_main_ref_store() public and use it
 . refs.c: kill register_ref_store(), add register_submodule_ref_store()
 . refs.c: flatten get_ref_store() a bit
 . refs: rename lookup_ref_store() to lookup_submodule_ref_store()
 . refs.c: introduce get_main_ref_store()
 . files-backend: remove the use of git_path()
 . files-backend: add and use files_refname_path()
 . files-backend: add and use files_reflog_path()
 . files-backend: move "logs/" out of TMP_RENAMED_LOG
 . files-backend: convert git_path() to strbuf_git_path()
 . files-backend: add and use files_packed_refs_path()
 . files-backend: make files_log_ref_write() static
 . refs.h: add forward declaration for structs used in this file
 . Merge branch 'mh/ref-remove-empty-directory' into nd/files-backend-git-dir
 . Merge branch 'mh/submodule-hash' into nd/files-backend-git-dir
 (this branch is tangled with nd/prune-in-worktree and nd/worktree-kill-parse-ref.)

 The "submodule" specific field in the ref_store structure is
 replaced with a more generic "gitdir" that can later be used also
 when dealing with ref_store that represents the set of refs visible
 from the other worktrees.

 Needs review.


* sb/checkout-recurse-submodules (2017-02-23) 15 commits
 - builtin/checkout: add --recurse-submodules switch
 - entry.c: update submodules when interesting
 - read-cache, remove_marked_cache_entries: wipe selected submodules.
 - unpack-trees: check if we can perform the operation for submodules
 - unpack-trees: pass old oid to verify_clean_submodule
 - update submodules: add submodule_move_head
 - update submodules: move up prepare_submodule_repo_env
 - submodules: introduce check to see whether to touch a submodule
 - update submodules: add a config option to determine if submodules are updated
 - update submodules: add submodule config parsing
 - connect_work_tree_and_git_dir: safely create leading directories
 - make is_submodule_populated gently
 - lib-submodule-update.sh: define tests for recursing into submodules
 - lib-submodule-update.sh: do not use ./. as submodule remote
 - lib-submodule-update.sh: reorder create_lib_submodule_repo

 "git checkout" is taught --recurse-submodules option.

 Needs review.


* tg/stash-push (2017-02-27) 7 commits
 - SQUASH???
 - stash: allow pathspecs in the no verb form
 - stash: use stash_push for no verb form
 - stash: teach 'push' (and 'create_stash') to honor pathspec
 - stash: refactor stash_create
 - stash: add test for the create command line arguments
 - stash: introduce push verb

 Allow "git stash" to take pathspec so that the local changes can be
 stashed away only partially.

 Expecting a reroll.
 I think this is almost there.
 cf. <20170225213306.2410-1-t.gummerer@gmail.com>


* bc/object-id (2017-02-22) 19 commits
 - wt-status: convert to struct object_id
 - builtin/merge-base: convert to struct object_id
 - Convert object iteration callbacks to struct object_id
 - sha1_file: introduce an nth_packed_object_oid function
 - refs: simplify parsing of reflog entries
 - refs: convert each_reflog_ent_fn to struct object_id
 - reflog-walk: convert struct reflog_info to struct object_id
 - builtin/replace: convert to struct object_id
 - Convert remaining callers of resolve_refdup to object_id
 - builtin/merge: convert to struct object_id
 - builtin/clone: convert to struct object_id
 - builtin/branch: convert to struct object_id
 - builtin/grep: convert to struct object_id
 - builtin/fmt-merge-message: convert to struct object_id
 - builtin/fast-export: convert to struct object_id
 - builtin/describe: convert to struct object_id
 - builtin/diff-tree: convert to struct object_id
 - builtin/commit: convert to struct object_id
 - hex: introduce parse_oid_hex

 "uchar [40]" to "struct object_id" conversion continues.

 Now at v5.
 cf. <20170221234737.894681-1-sandals@crustytoothpaste.net>


* jh/mingw-openssl-sha1 (2017-02-09) 1 commit
 - mingw: use OpenSSL's SHA-1 routines

 Windows port wants to use OpenSSL's implementation of SHA-1
 routines, so let them.

 Kicked back to 'pu'
 cf. <9913e513-553e-eba6-e81a-9c21030dd767@kdbg.org>


* sg/completion-refs-speedup (2017-02-13) 13 commits
 - squash! completion: fill COMPREPLY directly when completing refs
 - completion: fill COMPREPLY directly when completing refs
 - completion: list only matching symbolic and pseudorefs when completing refs
 - completion: let 'for-each-ref' sort remote branches for 'checkout' DWIMery
 - completion: let 'for-each-ref' filter remote branches for 'checkout' DWIMery
 - completion: let 'for-each-ref' strip the remote name from remote branches
 - completion: let 'for-each-ref' and 'ls-remote' filter matching refs
 - completion: don't disambiguate short refs
 - completion: don't disambiguate tags and branches
 - completion: support excluding full refs
 - completion: support completing full refs after '--option=refs/<TAB>'
 - completion: wrap __git_refs() for better option parsing
 - completion: remove redundant __gitcomp_nl() options from _git_commit()

 The refs completion for large number of refs has been sped up,
 partly by giving up disambiguating ambiguous refs and partly by
 eliminating most of the shell processing between 'git for-each-ref'
 and 'ls-remote' and Bash's completion facility.

 What's the donness of this topic?


* jk/no-looking-at-dotgit-outside-repo-final (2016-10-26) 1 commit
  (merged to 'next' on 2017-02-27 at 7373a1b73d)
 + setup_git_env: avoid blind fall-back to ".git"

 This is the endgame of the topic to avoid blindly falling back to
 ".git" when the setup sequence said we are _not_ in Git repository.
 A corner case that happens to work right now may be broken by a
 call to die("BUG").

 Will cook in 'next'.


* jc/merge-drop-old-syntax (2015-04-29) 1 commit
  (merged to 'next' on 2017-02-27 at 2c0f5f73d8)
 + merge: drop 'git merge <message> HEAD <commit>' syntax

 Stop supporting "git merge <message> HEAD <commit>" syntax that has
 been deprecated since October 2007, and issues a deprecation
 warning message since v2.5.0.

 Will cook in 'next'.


* jc/bundle (2016-03-03) 6 commits
 - index-pack: --clone-bundle option
 - Merge branch 'jc/index-pack' into jc/bundle
 - bundle v3: the beginning
 - bundle: keep a copy of bundle file name in the in-core bundle header
 - bundle: plug resource leak
 - bundle doc: 'verify' is not about verifying the bundle

 The beginning of "split bundle", which could be one of the
 ingredients to allow "git clone" traffic off of the core server
 network to CDN.

--------------------------------------------------
[Discarded]

* sb/push-make-submodule-check-the-default (2017-01-26) 2 commits
 . Revert "push: change submodule default to check when submodules exist"
 . push: change submodule default to check when submodules exist

 Turn the default of "push.recurseSubmodules" to "check" when
 submodules seem to be in use.

 Retracted.


* ls/submodule-config-ucase (2017-02-15) 2 commits
 . submodule config does not apply to upper case submodules?
 . t7400: cleanup "submodule add clone shallow submodule" test

 Demonstrate a breakage in handling submodule.UPPERCASENAME.update
 configuration variables.

 Superseded by jc/config-case-cmdline.


* js/curl-empty-auth-set-by-default (2017-02-22) 1 commit
 . http(s): automatically try NTLM authentication first

 Flip "http.emptyAuth" on by default to help OOB experience for
 users of HTTP Negotiate authentication scheme.

 Superseded by jk/http-auth topic.


* jc/config-case-cmdline (2017-02-21) 3 commits
 . config: squelch stupid compiler
 . config: reject invalid VAR in 'git -c VAR=VAL command'
 . config: preserve <subsection> case for one-shot config on the command line

 The code to parse "git -c VAR=VAL cmd" and set configuration
 variable for the duration of cmd had two small bugs, which have
 been fixed.

 Superseded by jc/config-case-cmdline-take-2


* lt/oneline-decoration-at-end (2017-02-21) 2 commits
 . log: fix regression to "--source" when "--decorate" was updated
 . show decorations at the end of the line

 The output from "git log --oneline --decorate" has been updated to
 show the extra information at the end of the line, not near the
 front.

 Retracted.
 cf. <CA+55aFwT2HUBzZO8Gpt9tHoJtdRxv9oe3TDoSH5jcEOixRNBXg@mail.gmail.com>


* sk/parse-remote-cleanup (2017-02-21) 2 commits
 . Revert "parse-remote: remove reference to unused op_prep"
 . parse-remote: remove reference to unused op_prep

 Code clean-up.

 Will discard.
 There may be third-party scripts that are dot-sourcing this one.



^ permalink raw reply

* [PATCH] http: attempt updating base URL only if no error
From: Jonathan Tan @ 2017-02-28  2:53 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, peff

http.c supports HTTP redirects of the form

  http://foo/info/refs?service=git-upload-pack
  -> http://anything
  -> http://bar/info/refs?service=git-upload-pack

(that is to say, as long as the Git part of the path and the query
string is preserved in the final redirect destination, the intermediate
steps can have any URL). However, if one of the intermediate steps
results in an HTTP exception, a confusing "unable to update url base
from redirection" message is printed instead of a Curl error message
with the HTTP exception code.

This was introduced by 2 commits. Commit c93c92f ("http: update base
URLs when we see redirects", 2013-09-28) introduced a best-effort
optimization that required checking if only the "base" part of the URL
differed between the initial request and the final redirect destination,
but it performed the check before any HTTP status checking was done. If
something went wrong, the normal code path was still followed, so this
did not cause any confusing error messages until commit 6628eb4 ("http:
always update the base URL for redirects", 2016-12-06), which taught
http to die if the non-"base" part of the URL differed.

Therefore, teach http to check the HTTP status before attempting to
check if only the "base" part of the URL differed. This commit teaches
http_request_reauth to return early without updating options->base_url
upon an error; the only invoker of this function that passes a non-NULL
"options" is remote-curl.c (through "http_get_strbuf"), which only uses
options->base_url for an informational message in the situations that
this commit cares about (that is, when the return value is not HTTP_OK).

The included test checks that the redirect scheme at the beginning of
this commit message works, and that returning a 502 in the middle of the
redirect scheme produces the correct result. Note that this is different
from the test in commit 6628eb4 ("http: always update the base URL for
redirects", 2016-12-06) in that this commit tests that a Git-shaped URL
(http://.../info/refs?service=git-upload-pack) works, whereas commit
6628eb4 tests that a non-Git-shaped URL
(http://.../info/refs/foo?service=git-upload-pack) does not work (even
though Git is processing that URL) and is an error that is fatal, not
silently swallowed.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 http.c                     | 3 +++
 t/lib-httpd/apache.conf    | 9 +++++++++
 t/t5550-http-fetch-dumb.sh | 9 +++++++++
 3 files changed, 21 insertions(+)

diff --git a/http.c b/http.c
index 90a1c0f11..1df186894 100644
--- a/http.c
+++ b/http.c
@@ -1727,6 +1727,9 @@ static int http_request_reauth(const char *url,
 {
 	int ret = http_request(url, result, target, options);
 
+	if (ret != HTTP_OK && ret != HTTP_REAUTH)
+		return ret;
+
 	if (options && options->effective_url && options->base_url) {
 		if (update_url_from_redirect(options->base_url,
 					     url, options->effective_url)) {
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 69174c6e3..0642ae7e6 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -133,6 +133,15 @@ RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302]
 RewriteRule ^/loop-redir/x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-(.*) /$1 [R=302]
 RewriteRule ^/loop-redir/(.*)$ /loop-redir/x-$1 [R=302]
 
+# redir-to/502/x?y -> really-redir-to?path=502/x&qs=y which returns 502
+# redir-to/x?y -> really-redir-to?path=x&qs=y -> x?y
+RewriteCond %{QUERY_STRING} ^(.*)$
+RewriteRule ^/redir-to/(.*)$ /really-redir-to?path=$1&qs=%1 [R=302]
+RewriteCond %{QUERY_STRING} ^path=502/(.*)&qs=(.*)$
+RewriteRule ^/really-redir-to$ - [R=502,L]
+RewriteCond %{QUERY_STRING} ^path=(.*)&qs=(.*)$
+RewriteRule ^/really-redir-to$ /%1?%2 [R=302]
+
 # The first rule issues a client-side redirect to something
 # that _doesn't_ look like a git repo. The second rule is a
 # server-side rewrite, so that it turns out the odd-looking
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
index aeb3a63f7..2d3b1e9f9 100755
--- a/t/t5550-http-fetch-dumb.sh
+++ b/t/t5550-http-fetch-dumb.sh
@@ -378,5 +378,14 @@ test_expect_success 'http-alternates triggers not-from-user protocol check' '
 		clone $HTTPD_URL/dumb/evil.git evil-user
 '
 
+test_expect_success 'can redirect through non-"info/refs?service=git-upload-pack" URL' '
+	git clone "$HTTPD_URL/redir-to/dumb/repo.git"
+'
+
+test_expect_success 'print HTTP error when any intermediate redirect throws error' '
+	test_must_fail git clone "$HTTPD_URL/redir-to/502" 2> stderr &&
+	test_i18ngrep "unable to access.*/redir-to/502" stderr
+'
+
 stop_httpd
 test_done
-- 
2.11.0.483.g087da7b7c-goog


^ permalink raw reply related

* Re: [PATCH 4/4] ident: do not ignore empty config name/email
From: Christian Couder @ 2017-02-28  5:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Dennis Kaarsemaker, Jeff King, bs.x.ttp, git
In-Reply-To: <xmqq1sujwek2.fsf@gitster.mtv.corp.google.com>

On Mon, Feb 27, 2017 at 9:42 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Dennis Kaarsemaker <dennis@kaarsemaker.net> writes:
>
>> On Thu, 2017-02-23 at 23:18 -0500, Jeff King wrote:
>>> On Thu, Feb 23, 2017 at 08:11:11PM -0800, Junio C Hamano wrote:
>>>
>>> > > So I dunno. I could really go either way on it. Feel free to drop it, or
>>> > > even move it into a separate topic to be cooked longer.
>>> >
>>> > If it were 5 years ago, it would have been different, but I do not
>>> > think cooking it longer in 'next' would smoke out breakages in
>>> > obscure scripts any longer.  Git is used by too many people who have
>>> > never seen its source these days.
>>>
>>> Yeah, I have noticed that, too. I wonder if it would be interesting to
>>> cut "weeklies" or something of "master" or even "next" that people could
>>> install with a single click.
>>>
>>> Of course it's not like we have a binary installer in the first place,
>>> so I guess that's a prerequisite.
>>
>> I provide daily[*] snapshots of git's master and next tree as packages
>> for Ubuntu, Debian, Fedora and CentOS on launchpad and SuSE's
>> openbuildservice. If there's sufficient interest in this (I know of
>> only a few users), I can try to put more effort into this.
>
> That sounds handy for people who do not build from the source
> themselves.
>
> Christian, perhaps rev-news can help advertising Dennis's effort to
> recruit like-minded souls?

Yeah, I had already noticed this thread and now Jakub has mentioned it on:

https://github.com/git/git.github.io/issues/231

so yeah we will advertise it one way or another.

^ permalink raw reply

* Typesafer git hash patch
From: Linus Torvalds @ 2017-02-28  6:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List

So because of the whole SHA1 discussion, I started looking at what it
would involve to turn

    unsigned char *sha1

style arguments (and various structure members) in the git source into

   typedef struct { ... } hash_t;

   hash_t *hash;

The answer is that it's pretty painful - more so than I expected (I
looked at it _looong_ ago and decided it was painful - and it has
become more painful as git has grown).

But once I got started I just continued through the slog.

Having the hashes be more encapsulated does seem to make things better
in many ways. What I did was to also just unify the notion of "hash_t"
and "struct object_id", so the two are entirely interchangeable. That
actually can clean up some code, because right now we have duplicate
interfaces for some things that take an oid pointer and others take a
"const unsigned char *sha1", and that duplication essentially can go
away. I didn't do any of that, I tried to keep it as as brute-force
stupid conversion.

I saw that somebody is actually looking at doing this "well" - by
doing it in many smaller steps. I tried. I gave up. The "unsigned char
*sha1" model is so ingrained that doing it incrementally just seemed
like a lot of pain. But it might be the right approach.

It might particularly be the right approach considering the size of the patch:

 216 files changed, 4174 insertions(+), 4080 deletions(-)

which is pretty nasty. The good news is that my patch passes all the
tests, and while it's big it's mostly very very mindless, and a lot of
it looks like cleanups, and the lines are generally shorter, eg

-               const unsigned char *mb = result->item->object.oid.hash;
-               if (!hashcmp(mb, current_bad_oid->hash)) {

turns into

+               const hash_t *mb = &result->item->object.oid;
+               if (!hashcmp(mb, current_bad_oid)) {

but I ended up also renaming a lot of common "sha1" as "hash", which
adds to the noise in that patch.

NOTE! It doesn't actually _fix_ the SHA1-centricity in any way, but it
makes it a bit more obvious where the bigger problems are. Not that
anybody would be surprised by what they are, but as part of writing
the patch it did kind of pinpoint most of them, and about 30 of those
new lines are added

 /* FIXME! Hardcoded hash sizes */
 /* FIXME! Lots of fixed-size hashes */
 /* FIXME! Fixed 20-byte hash usage */

with the rest of the added lines being a few helper functions and
splitting cache.h up a bit.

And as part of the type safety, I do think I may have found a bug:

show_one_mergetag():

                strbuf_addf(&verify_message, "tag %s names a non-parent %s\n",
                                    tag->tag, tag->tagged->oid.hash);

note how it prints out the "non-parent %s", but that's a SHA1 hash
that hasn't been converted to hex. Hmm?

Anyway, is anybody interested?  I warn you - it really is one big
patch on top of 2.12.

                   Linus

PS. Just for fun, I tried to look what it does when you then merge pu
or next.. You do get a fair number of merge conflicts because there's
just a lot of changes all around, but they look manageable. So merging
something like that would be painful, but it appears to not entirely
break other development.

^ permalink raw reply

* Git has been accepted as a GSoC 2017 mentor organization!
From: Christian Couder @ 2017-02-28  7:04 UTC (permalink / raw)
  To: git; +Cc: Stefan Beller, Johannes Schindelin, Matthieu Moy, Jeff King

Hi everyone,

I am happy to let you know that Git has been accepted as a GSoC mentor
organization again this year.

  https://summerofcode.withgoogle.com/organizations/

I invited Dscho and Stefan as potential mentors for Git. I also
invited Junio to give him access to students proposals and the
opportunity to comment on them.

Tell me if you want an invitation to mentor too. There is no
commitment to mentor anyone for now if you accept the invitation. This
will be decided later. You will just get access to the proposals and
be able to comment on them.

As a reminder, our GSoC related pages are:

  http://git.github.io/SoC-2017-Ideas/
  http://git.github.io/SoC-2017-Microprojects/

They could still be improved which can be done through:

https://github.com/git/git.github.io/

Thanks in advance,
Christian.

(PS: Matthieu, yeah I used your email from last year as a template for
this one, thanks!)

^ permalink raw reply

* Re: [RFC] - url-safe base64 commit-id's
From: Bryan Turner @ 2017-02-28  6:30 UTC (permalink / raw)
  Cc: Git Users
In-Reply-To: <CAAj3zPzwWr4u1qSMp5CwVMzExW2eg9LQ7t7RX-5m6fRRGh9pcA@mail.gmail.com>

On Mon, Feb 27, 2017 at 6:27 PM, G. Sylvie Davies
<sylvie@bit-booster.com> wrote:
> Is there any appetite for base64'd commit-id's, using the url-safe
> variant (e.g. RFC 4648 [1] with padding removed)?
>
> And so this:
> 712bad335dfa9c410a83f9873614a19726acb3a8
>
> Becomes this:
> cSutM136nEEKg_mHNhShlyass6g
>
>
> Under the hood things cannot change (e.g., ".git/objects/71/") because
> file systems are not always case sensitive.
>
> But for "git log" and "git show" output it would be nice. And helps
> with ambiguous commit id's too if you only want to specify a 7
> character commit-id, since that encodes 42 bits instead of 28 bits.
> I've run into problems with maximum command length on windows (32767
> chars) because I was specifying so many commit-ids on the command-line
> that I blew past that limit. This would help there, too.

Depending on the command, have you considered using stdin instead? git log,
for example, is perfectly happy to read commit IDs from stdin instead of
the command line.

In general, I think the pattern of getting away from command line arguments
is better than trying to shoehorn more data into the same character limit.
Base64 encoding might help get a few more arguments into the available
limit, but in the end it's not going to solve the underlying problem.

>
> Might be particularly helpful with the transition to a new hash.
> e.g., a 43 character Base64 id instead of a 64 character hex id.
>
>
> - Sylvie
>
> [1] - https://tools.ietf.org/html/rfc4648#page-7

^ permalink raw reply

* Re: [BUG] branch renamed to 'HEAD'
From: Jacob Keller @ 2017-02-28  7:58 UTC (permalink / raw)
  To: Jeff King; +Cc: Junio C Hamano, Karthik Nayak, Luc Van Oostenryck, Git List
In-Reply-To: <20170228005302.k6fyfinaxyl3ti76@sigill.intra.peff.net>

On Mon, Feb 27, 2017 at 4:53 PM, Jeff King <peff@peff.net> wrote:
> On Mon, Feb 27, 2017 at 04:33:36PM -0800, Junio C Hamano wrote:
>
>> A flag to affect the behaviour (as opposed to &flag as a secondary
>> return value, like Peff's patch does) can be made to work.  Perhaps
>> a flag that says "keep the input as is if the result is not a local
>> branch name" would pass an input "@" intact and that may be
>> sufficient to allow "git branch -m @" to rename the current branch
>> to "@" (I do not think it is a sensible rename, though ;-).  But
>> probably some callers need to keep the original input and compare
>> with the result to see if we expanded anything if we go that route.
>> At that point, I am not sure if there are much differences in the
>> ease of use between the two approaches.
>
> I just went into more detail in my reply to Jacob, but I do think this
> is a workable approach (and fortunately we seem to have banned bare "@"
> as a name, along with anything containing "@{}", so I think we would end
> up rejecting these nonsense names).
>
> I'll see if I can work up a patch. We'll still need to pass the flag
> around through the various functions, but at least it will be a flag and
> not a confusing negated out-parameter.
>
> -Peff

Yes, this is pretty much what I had imagined. I look forward to seeing
the patch.

Thanks,
Jake

^ permalink raw reply

* [PATCH 2/2] docs/diffcore: unquote "Complete Rewrites" in headers
From: Patrick Steinhardt @ 2017-02-28  8:59 UTC (permalink / raw)
  To: git; +Cc: Patrick Steinhardt, Patrick Steinhardt
In-Reply-To: <2882e77a58e4219d60a39827c3ea8d4537d5178a.1488272203.git.patrick.steinhardt@elego.de>

The gitdiffcore documentation quotes the term "Complete Rewrites" in
headers for no real gain. This would make sense if the term could be
easily confused if not properly grouped together. But actually, the term
is quite obvious and thus does not really need any quoting, especially
regarding that it is not used anywhere else.

But more importanly, this brings up a bug when rendering man pages: when
trying to render quotes inside of a section header, we end up with
quotes which have been misaligned to the end of line. E.g.

    diffcore-break: For Splitting Up Complete Rewrites
    --------------------------------------------------

renders as

    DIFFCORE-BREAK: FOR SPLITTING UP  COMPLETE REWRITES""

, which is obviously wrong. While this is fixable for the man pages by
using double-quotes (e.g. ""COMPLETE REWRITES""), this again breaks it
for our generated HTML pages.

So fix the issue by simply dropping quotes inside of section headers,
which is currently only done for the term "Complete Rewrites".

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---

The obvious other route here would be to fix how the stylesheets
handle quoting inside of these headers. But after taking a short
look, I didn't really get how our stylesheets actually stitch
together and as such bailed from doing so.

 Documentation/gitdiffcore.txt | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt
index cf009a187..c0a60f315 100644
--- a/Documentation/gitdiffcore.txt
+++ b/Documentation/gitdiffcore.txt
@@ -84,8 +84,8 @@ format sections of the manual for 'git diff-{asterisk}' commands) or
 diff-patch format.
 
 
-diffcore-break: For Splitting Up "Complete Rewrites"
-----------------------------------------------------
+diffcore-break: For Splitting Up Complete Rewrites
+--------------------------------------------------
 
 The second transformation in the chain is diffcore-break, and is
 controlled by the -B option to the 'git diff-{asterisk}' commands.  This is
@@ -177,8 +177,8 @@ the expense of making it slower.  Without `--find-copies-harder`,
 copied happened to have been modified in the same changeset.
 
 
-diffcore-merge-broken: For Putting "Complete Rewrites" Back Together
---------------------------------------------------------------------
+diffcore-merge-broken: For Putting Complete Rewrites Back Together
+------------------------------------------------------------------
 
 This transformation is used to merge filepairs broken by
 diffcore-break, and not transformed into rename/copy by
-- 
2.12.0


^ permalink raw reply related

* [PATCH 1/2] docs/diffcore: fix grammar in diffcore-rename header
From: Patrick Steinhardt @ 2017-02-28  8:59 UTC (permalink / raw)
  To: git; +Cc: Patrick Steinhardt, Patrick Steinhardt

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 Documentation/gitdiffcore.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt
index 46bc6d077..cf009a187 100644
--- a/Documentation/gitdiffcore.txt
+++ b/Documentation/gitdiffcore.txt
@@ -119,7 +119,7 @@ the original is used), and can be customized by giving a number
 after "-B" option (e.g. "-B75" to tell it to use 75%).
 
 
-diffcore-rename: For Detection Renames and Copies
+diffcore-rename: For Detecting Renames and Copies
 -------------------------------------------------
 
 This transformation is used to detect renames and copies, and is
-- 
2.12.0


^ permalink raw reply related


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