Git development
 help / color / mirror / Atom feed
* [PATCH 5/6] Add MD support for fetch, pull, and push.
From: Bill Zaumen @ 2011-12-21  7:12 UTC (permalink / raw)
  To: git, peff, pclouds, gitster

A new capability, "mds-check" is defined. When present, a client will
(when possible and useful) send the server a SHA-1 value and a message
digest, separated by a '-'.  This is used to detect hash collisions,
with a goal of finding problems early if a malicious attempt is made
to forge commits with different commits with the same SHA-1 value in
different repositories.  It is a simple, fast test - a look-up and a
comparison.

Signed-off-by: Bill Zaumen <bill.zaumen+git@gmail.com>
---
 builtin/fetch-pack.c   |   29 +++++++++++-
 builtin/receive-pack.c |  117 +++++++++++++++++++++++++++++++++++++++++++-----
 builtin/send-pack.c    |   26 ++++++++++-
 http.c                 |   19 ++++++--
 t/t5500-fetch-pack.sh  |   10 +++--
 t/t5510-fetch.sh       |   12 ++++-
 upload-pack.c          |   11 ++++-
 7 files changed, 196 insertions(+), 28 deletions(-)

diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 6207ecd..2f5b7ef 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -18,6 +18,8 @@ static int prefer_ofs_delta = 1;
 static int no_done;
 static int fetch_fsck_objects = -1;
 static int transfer_fsck_objects = -1;
+static int mds_check = 0;
+
 static struct fetch_pack_args args = {
 	/* .uploadpack = */ "git-upload-pack",
 };
@@ -390,9 +392,25 @@ static int find_common(int fd[2], unsigned char *result_sha1,
 	flushes = 0;
 	retval = -1;
 	while ((sha1 = get_rev())) {
-		packet_buf_write(&req_buf, "have %s\n", sha1_to_hex(sha1));
-		if (args.verbose)
-			fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
+		if (mds_check) {
+			mdigest_t digest;
+			if (has_sha1_file_digest(sha1, &digest)) {
+				packet_buf_write(&req_buf, "have %s\n",
+						 sha1_to_hex_digest(sha1,
+								    &digest));
+
+			} else {
+				packet_buf_write(&req_buf, "have %s\n",
+						 sha1_to_hex(sha1));
+			}
+			if (args.verbose)
+				fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
+		} else {
+			packet_buf_write(&req_buf, "have %s\n",
+					 sha1_to_hex(sha1));
+			if (args.verbose)
+				fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
+		}
 		in_vain++;
 		if (flush_at <= ++count) {
 			int ack;
@@ -807,6 +825,11 @@ static struct ref *do_fetch_pack(int fd[2],
 			fprintf(stderr, "Server supports ofs-delta\n");
 	} else
 		prefer_ofs_delta = 0;
+	if (server_supports("mds-check")) {
+		if (args.verbose)
+			fprintf(stderr, "Server supports mds-check\n");
+		mds_check = 1;
+	}
 	if (everything_local(&ref, nr_match, match)) {
 		packet_flush(fd[1]);
 		goto all_done;
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index d2dcb7e..b9d1c1f 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -122,7 +122,8 @@ static int show_ref(const char *path, const unsigned char *sha1, int flag, void
 	else
 		packet_write(1, "%s %s%c%s%s\n",
 			     sha1_to_hex(sha1), path, 0,
-			     " report-status delete-refs side-band-64k",
+			     " report-status delete-refs side-band-64k"
+			     " mds-check",
 			     prefer_ofs_delta ? " ofs-delta" : "");
 	sent_capabilities = 1;
 	return 0;
@@ -709,37 +710,131 @@ static struct command *read_head_info(void)
 	struct command *commands = NULL;
 	struct command **p = &commands;
 	for (;;) {
-		static char line[1000];
+		static char line[1500];
 		unsigned char old_sha1[20], new_sha1[20];
 		struct command *cmd;
 		char *refname;
 		int len, reflen;
+		int has_old_sha1_digest = 0;
+		int has_new_sha1_digest = 0;
+		mdigest_t old_sha1_digest;
+		mdigest_t new_sha1_digest;
+		mdigest_t digest;
+		int old_hashlen = 40;
+		int new_hashlen = 40;
+		int hashlen = 81; /* includes blank between two hashes */
+		int digest_field_len = 0;
+
+		mdigest_clear(&old_sha1_digest);
+		mdigest_clear(&new_sha1_digest);
 
 		len = packet_read_line(0, line, sizeof(line));
 		if (!len)
 			break;
 		if (line[len-1] == '\n')
 			line[--len] = 0;
-		if (len < 83 ||
-		    line[40] != ' ' ||
-		    line[81] != ' ' ||
-		    get_sha1_hex(line, old_sha1) ||
-		    get_sha1_hex(line + 41, new_sha1))
+		if (len > (old_hashlen + 1) && line[old_hashlen] == '-') {
+			digest_field_len = 1
+				+ get_hex_field_size(line+old_hashlen+1);
+		}
+		if (len > (old_hashlen + digest_field_len) &&
+		    line[old_hashlen] == '-') {
+			old_hashlen += digest_field_len;
+			hashlen += digest_field_len;
+			digest_field_len = 0;
+			if (len > (old_hashlen + 1)
+			    && line[old_hashlen] == '-') {
+				digest_field_len = 1 +
+					get_hex_field_size(line+old_hashlen+1);
+			}
+			if (len > (old_hashlen + digest_field_len + 1) &&
+			    line[old_hashlen] == '-') {
+				old_hashlen += digest_field_len;
+				hashlen += digest_field_len;
+			}
+		}
+		if (line[old_hashlen] != ' ') {
+			die("protocol error: expected old/new/ref, got '%s'",
+			    line);
+		}
+		digest_field_len = 0;
+		if (len > hashlen + 1 && line[hashlen] == '-') {
+			digest_field_len = 1 +
+			  get_hex_field_size(line+hashlen+1);
+		}
+		if (len > (hashlen + digest_field_len + 1) &&
+		    line[hashlen] == '-') {
+			new_hashlen += digest_field_len;
+			hashlen += digest_field_len;
+			digest_field_len = 0;
+			if (len > (hashlen + 1)
+			    && line[hashlen] == '-') {
+				digest_field_len = 1 +
+					get_hex_field_size(line+hashlen+1);
+			}
+			if (len > (hashlen + digest_field_len + 1) &&
+			    line[hashlen] == '-') {
+				new_hashlen += digest_field_len;
+				hashlen += digest_field_len;
+			}
+		}
+		if (line[hashlen] != ' ') {
 			die("protocol error: expected old/new/ref, got '%s'",
 			    line);
+		}
+
+		if (len < hashlen + 1 ||
+		    line[old_hashlen] != ' ' ||
+		    line[hashlen] != ' ' ||
+		    get_sha1_hex_digest(line, old_sha1,
+				     &has_old_sha1_digest, &old_sha1_digest) ||
+		    get_sha1_hex_digest(line + old_hashlen + 1, new_sha1,
+					&has_new_sha1_digest,
+					&new_sha1_digest)) {
+			die("protocol error: expected old/new/ref, got '%s'",
+			    line);
+		}
+
+		if (has_old_sha1_digest &&
+		    has_sha1_file_digest(old_sha1, &digest)) {
+			if (mdigest_tst(&old_sha1_digest, &digest)) {
+				die("hash collision for %s",
+				    sha1_to_hex(old_sha1));
+			}
+		}
+
+
+		if (has_new_sha1_digest &&
+		    has_sha1_file_digest(new_sha1, &digest)) {
+			if (mdigest_tst(&new_sha1_digest, &digest)) {
+				die("hash collision for %s",
+				    sha1_to_hex(new_sha1));
+			}
+		}
 
-		refname = line + 82;
+		refname = line + hashlen + 1;
 		reflen = strlen(refname);
-		if (reflen + 82 < len) {
+		if (reflen + hashlen + 1 < len) {
 			if (strstr(refname + reflen + 1, "report-status"))
 				report_status = 1;
 			if (strstr(refname + reflen + 1, "side-band-64k"))
 				use_sideband = LARGE_PACKET_MAX;
 		}
-		cmd = xcalloc(1, sizeof(struct command) + len - 80);
+		/*
+		 * Without the additional digests,
+		 *   old_hashlen + new_hashlen = 80
+		 *   hashlen = 81,
+		 *   hashlen + 1 = 82
+		 * which puts the same numeric values into the last argument
+		 * of xcalloc, and the second & third argument of memcpy
+		 * that were used in commit
+		 * fc14b89a7e6899b8ac3b5751ec2d8c98203ea4c2.
+		 */
+		cmd = xcalloc(1, sizeof(struct command) + len
+			      - (old_hashlen + new_hashlen));
 		hashcpy(cmd->old_sha1, old_sha1);
 		hashcpy(cmd->new_sha1, new_sha1);
-		memcpy(cmd->ref_name, line + 82, len - 81);
+		memcpy(cmd->ref_name, line + hashlen + 1, len - (hashlen));
 		*p = cmd;
 		p = &cmd->next;
 	}
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index cd1115f..1eb9704 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -250,6 +250,7 @@ int send_pack(struct send_pack_args *args,
 	int allow_deleting_refs = 0;
 	int status_report = 0;
 	int use_sideband = 0;
+	int mds_check = 0;
 	unsigned cmds_sent = 0;
 	int ret;
 	struct async demux;
@@ -263,6 +264,8 @@ int send_pack(struct send_pack_args *args,
 		args->use_ofs_delta = 1;
 	if (server_supports("side-band-64k"))
 		use_sideband = 1;
+	if (server_supports("mds-check"))
+		mds_check = 1;
 
 	if (!remote_refs) {
 		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
@@ -298,8 +301,27 @@ int send_pack(struct send_pack_args *args,
 		if (args->dry_run) {
 			ref->status = REF_STATUS_OK;
 		} else {
-			char *old_hex = sha1_to_hex(ref->old_sha1);
-			char *new_hex = sha1_to_hex(ref->new_sha1);
+			char *old_hex, *new_hex;
+			if (mds_check) {
+				mdigest_t digest;
+				if (has_sha1_file_digest(ref->old_sha1,
+						      &digest)) {
+					old_hex = sha1_to_hex_digest
+						(ref->old_sha1, &digest);
+				} else {
+					old_hex = sha1_to_hex(ref->old_sha1);
+				}
+				if (has_sha1_file_digest(ref->new_sha1,
+						      &digest)) {
+					new_hex = sha1_to_hex_digest
+						(ref->new_sha1, &digest);
+				} else {
+					new_hex = sha1_to_hex(ref->new_sha1);
+				}
+			} else {
+				old_hex = sha1_to_hex(ref->old_sha1);
+				new_hex = sha1_to_hex(ref->new_sha1);
+			}
 
 			if (!cmds_sent && (status_report || use_sideband)) {
 				packet_buf_write(&req_buf, "%s %s %s%c%s%s",
diff --git a/http.c b/http.c
index 0ffd79c..e4e3ec7 100644
--- a/http.c
+++ b/http.c
@@ -1014,8 +1014,9 @@ int finish_http_pack_request(struct http_pack_request *preq)
 	struct packed_git **lst;
 	struct packed_git *p = preq->target;
 	char *tmp_idx;
+	char *tmp_mds;
 	struct child_process ip;
-	const char *ip_argv[8];
+	const char *ip_argv[10];
 
 	close_pack_index(p);
 
@@ -1028,14 +1029,20 @@ int finish_http_pack_request(struct http_pack_request *preq)
 	*lst = (*lst)->next;
 
 	tmp_idx = xstrdup(preq->tmpfile);
+	tmp_mds = xstrdup(preq->tmpfile);
 	strcpy(tmp_idx + strlen(tmp_idx) - strlen(".pack.temp"),
 	       ".idx.temp");
+	strcpy(tmp_mds + strlen(tmp_mds) - strlen(".pack.temp"),
+	       ".mds.temp");
+
 
 	ip_argv[0] = "index-pack";
 	ip_argv[1] = "-o";
 	ip_argv[2] = tmp_idx;
-	ip_argv[3] = preq->tmpfile;
-	ip_argv[4] = NULL;
+	ip_argv[3] = "-m";
+	ip_argv[4] = tmp_mds;
+	ip_argv[5] = preq->tmpfile;
+	ip_argv[6] = NULL;
 
 	memset(&ip, 0, sizeof(ip));
 	ip.argv = ip_argv;
@@ -1046,20 +1053,24 @@ int finish_http_pack_request(struct http_pack_request *preq)
 	if (run_command(&ip)) {
 		unlink(preq->tmpfile);
 		unlink(tmp_idx);
+		unlink(tmp_mds);
 		free(tmp_idx);
+		free(tmp_mds);
 		return -1;
 	}
 
 	unlink(sha1_pack_index_name(p->sha1));
 
 	if (move_temp_to_file(preq->tmpfile, sha1_pack_name(p->sha1))
-	 || move_temp_to_file(tmp_idx, sha1_pack_index_name(p->sha1))) {
+	 || move_temp_to_file(tmp_idx, sha1_pack_index_name(p->sha1))
+	 || move_temp_to_file(tmp_mds, sha1_pack_mds_name(p->sha1))) {
 		free(tmp_idx);
 		return -1;
 	}
 
 	install_packed_git(p);
 	free(tmp_idx);
+	free(tmp_mds);
 	return 0;
 }
 
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 9bf69e9..b6632d2 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -53,8 +53,8 @@ pull_to_client () {
 			git symbolic-ref HEAD refs/heads/`echo $heads \
 				| sed -e "s/^\(.\).*$/\1/"` &&
 
-			git fsck --full &&
-
+			git fsck --full  &&
+			test -z "`git count-objects -v -M | grep MD`" &&
 			mv .git/objects/pack/pack-* . &&
 			p=`ls -1 pack-*.pack` &&
 			git unpack-objects <$p &&
@@ -142,7 +142,8 @@ test_expect_success 'fsck in shallow repo' '
 test_expect_success 'simple fetch in shallow repo' '
 	(
 		cd shallow &&
-		git fetch
+		git fetch &&
+		test -z "`git count-objects -v -M | grep MD`"
 	)
 '
 
@@ -245,7 +246,8 @@ test_expect_success 'clone shallow object count' '
 		cd shallow &&
 		git count-objects -v
 	) > count.shallow &&
-	grep "^count: 52" count.shallow
+	grep "^count: 52" count.shallow  &&
+	test -z "`git count-objects -v -M | grep MD`"
 '
 
 test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index e88dbd5..5e3b8c6 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -14,6 +14,12 @@ test_bundle_object_count () {
 	test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l)
 }
 
+test_bundle_mds_count () {
+	git verify-pack -v -M "$1" >verify.out &&
+	test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | grep -v "<no md>" | wc -l)
+}
+
+
 test_expect_success setup '
 	echo >file original &&
 	git add file &&
@@ -214,7 +220,8 @@ test_expect_success 'bundle 1 has only 3 files ' '
 		cat
 	) <bundle1 >bundle.pack &&
 	git index-pack bundle.pack &&
-	test_bundle_object_count bundle.pack 3
+	test_bundle_object_count bundle.pack 3 &&
+	test_bundle_mds_count bundle.pack 3
 '
 
 test_expect_success 'unbundle 2' '
@@ -237,7 +244,8 @@ test_expect_success 'bundle does not prerequisite objects' '
 		cat
 	) <bundle3 >bundle.pack &&
 	git index-pack bundle.pack &&
-	test_bundle_object_count bundle.pack 3
+	test_bundle_object_count bundle.pack 3 &&
+	test_bundle_mds_count bundle.pack 3
 '
 
 test_expect_success 'bundle should be able to create a full history' '
diff --git a/upload-pack.c b/upload-pack.c
index 6f36f62..1e77826 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -320,11 +320,18 @@ static int got_sha1(char *hex, unsigned char *sha1)
 {
 	struct object *o;
 	int we_knew_they_have = 0;
+	int has_sha1_digest, has_digest;
+	mdigest_t sha1_digest, digest;
 
-	if (get_sha1_hex(hex, sha1))
+	if (get_sha1_hex_digest(hex, sha1, &has_sha1_digest, &sha1_digest))
 		die("git upload-pack: expected SHA1 object, got '%s'", hex);
 	if (!has_sha1_file(sha1))
 		return -1;
+	has_digest = has_sha1_file_digest(sha1, &digest);
+	if (has_sha1_digest && has_digest
+	    && mdigest_tst(&digest, &sha1_digest)) {
+		die("git upload-pack: SHA1 collision on MD for %s", hex);
+	}
 
 	o = lookup_object(sha1);
 	if (!(o && o->parsed))
@@ -719,7 +726,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 {
 	static const char *capabilities = "multi_ack thin-pack side-band"
 		" side-band-64k ofs-delta shallow no-progress"
-		" include-tag multi_ack_detailed";
+		" include-tag multi_ack_detailed" " mds-check";
 	struct object *o = parse_object(sha1);
 	const char *refname_nons = strip_namespace(refname);
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 6/6] Provide documentation for git message digest extensions
From: Bill Zaumen @ 2011-12-21  7:13 UTC (permalink / raw)
  To: git, peff, pclouds, gitster

The documentation includes API documentation for commands
and technical documentation for the message-digest-related
changes.  The technical documentation is in

* Documentation/technical/collision-detect.txt
* Documentation/technical/pack-format.txt

The modified commands are documented in

* Documentation/git-count-objects.txt
* Documentation/git-index-pack.txt
* Documentation/git-verify-pack.txt

Signed-off-by: Bill Zaumen <bill.zaumen+git@gmail.com>
---
 Documentation/git-count-objects.txt          |   12 +-
 Documentation/git-index-pack.txt             |   17 +-
 Documentation/git-verify-pack.txt            |   27 ++
 Documentation/technical/collision-detect.txt |  342 ++++++++++++++++++++++++++
 Documentation/technical/pack-format.txt      |   47 ++++
 5 files changed, 439 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/technical/collision-detect.txt

diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.txt
index 23c80ce..4cdbaf5 100644
--- a/Documentation/git-count-objects.txt
+++ b/Documentation/git-count-objects.txt
@@ -8,7 +8,7 @@ git-count-objects - Count unpacked number of objects and their disk consumption
 SYNOPSIS
 --------
 [verse]
-'git count-objects' [-v]
+'git count-objects' [-v] [-M]
 
 DESCRIPTION
 -----------
@@ -25,6 +25,16 @@ OPTIONS
 	objects, number of packs, disk space consumed by those packs,
 	and number of objects that can be removed by running
 	`git prune-packed`.
+-M::
+--count-md::
+	Report the number of loose objects with no stored message digests.
+	With the -v option, the number of missing "mds" files (these
+	contain the message digests for the SHA1 hashes in the corresponding
+	"idx" files) is reported, along with a count of the number of
+	mds files whose size is wrong (e.g., an index was created but the
+	existing MDS file was not updated) and a count of the number of
+	objects in pack files that do not have a stored message digest.
+	Values that are zero are not shown.
 
 GIT
 ---
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index 909687f..c9389f4 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -11,14 +11,14 @@ SYNOPSIS
 [verse]
 'git index-pack' [-v] [-o <index-file>] <pack-file>
 'git index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
-                 [<pack-file>]
+		 [-m <mds-file>] [<pack-file>]
 

 DESCRIPTION
 -----------
-Reads a packed archive (.pack) from the specified file, and
-builds a pack index file (.idx) for it.  The packed archive
-together with the pack index can then be placed in the
+Reads a packed archive (.pack) from the specified file, and builds a
+pack index file (.idx) and a pack mds file (.mds) for it.  The packed
+archive together with the pack index can then be placed in the
 objects/pack/ directory of a git repository.
 

@@ -35,6 +35,14 @@ OPTIONS
 	fails if the name of packed archive does not end
 	with .pack).
 
+-m <mds-file>::
+	Write the generated pack mds file into the specified.
+	file Without this option, the name of the pack mds
+	file is constructed from the name of packed archive
+	file by replacing .pack with .idx (and the program
+	fails if the name of packed archive does not end
+	with .pack).
+
 --stdin::
 	When this flag is provided, the pack is read from stdin
 	instead and a copy is then written to <pack-file>. If
@@ -74,7 +82,6 @@ OPTIONS
 --strict::
 	Die, if the pack contains broken objects or links.
 
-
 Note
 ----
 
diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt
index cd23076..f69ed3f 100644
--- a/Documentation/git-verify-pack.txt
+++ b/Documentation/git-verify-pack.txt
@@ -33,6 +33,19 @@ OPTIONS
 	Do not verify the pack contents; only show the histogram of delta
 	chain length.  With `--verbose`, list of objects is also shown.
 
+-M::
+--show-mds::
+	Show the message digests along with the 40-character object names
+	(SHA1 value in hexidecimal). Ignored if --stat-only is set. If
+	--verbose is not set, only the table indexed by object names is
+	shown, although the files will be verified.  The message digests
+	printed are the actual ones - if the MDS file does not contain these,
+	the verification will fail.  The message digests will be
+	prefaced with a two-byte code indicating the type of digest.
+	The values (n hexadecimal) are 01 for a CRC, 05 for SHA-1, 08
+	for SHA-256, and 10 for SHA-512.  If the digest stored does
+	not match the actual digest, the actual one is printed as well.
+
 \--::
 	Do not interpret any more arguments as options.
 
@@ -48,6 +61,20 @@ for objects that are not deltified in the pack, and
 
 for objects that are deltified.
 
+When the -M option is used, the offset-in-pack field is followed by an
+entry giving the message digest.  The format used is:
+
+      md=0xHEX_VALUE
+
+when a message digest exists, and
+
+     <no md>
+
+when a message digest does not exist.  These entries precede the depth
+entry for deltified objects.  A non-existent message digest will be shown
+only if the MDS file is missing - while the MDS-file format allows missing
+entries, the file will not be considered valid.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/technical/collision-detect.txt b/Documentation/technical/collision-detect.txt
new file mode 100644
index 0000000..d5a4364
--- /dev/null
+++ b/Documentation/technical/collision-detect.txt
@@ -0,0 +1,342 @@
+Hash-Collision Detection using Message Digests
+=============================
+
+Initially Git used a SHA-1 hash as an object ID under the assumption
+that a hash collision would never occur in practice. While an
+accidental SHA-1 collision is extremely unlikely, it is possible,
+although very expensive, to generate multiple files with the same
+SHA-1 value in under 2^57 operations.  With computer performance
+increasing significantly from one year to the next, Git's assumptions
+about SHA-1 will eventually not hold in the case of a malicious
+attempt to damage a project.  One should note that just because the
+probability of a SHA-1 collision occurring accidentally is extremely
+low does not mean a priori that SHA-1 provides an adequate safety
+margin for preventing a malicious attempt to damage repositories and a
+discussion below outlines some of the issues regarding this
+possibility.
+
+While one could modify Git to use SHA-224, SHA-256, SHA-384, or
+SHA-512 instead of SHA-1, the change would have to support the
+original format as well (in order to deal with existing Git
+repositories). While one could convert an existing repository to use
+the new hash function, this would require rewriting every object,
+including trees and commits.  The outcome would be problematic given
+the existence of email and documentation that might name commits by
+their SHA-1 hashes. One should note that Git performs a byte-by-byte
+check for hash collisions when a pack file is indexed.  Unfortunately,
+during fetch or pull operations, Git tries to avoid copying objects
+when a peer already has a copy, and this is determined solely on the
+basis of SHA-1 hashes.
+
+The following describes a modification to Git's initial design that is
+(a) relatively easy to implement, (b) is compatible with and can
+interoperate with older versions of Git (both the program and the
+repositories) (c) has a small computational overhead, and (d)
+increases security substantially, with a goal of detecting hash
+collisions early and automatically.  Because the implementation is
+relatively simple and the overhead very low, it makes sense to
+incorporate this change (or some alternative) before the security
+issue becomes a serious problem.
+
+Although Git generally uses that assumption that there will never be a
+hash collision using SHA-1 in practice, under some circumstances, Git
+will detect collisions via a byte-by-byte comparison as objects are
+added to the repository or as pack files are indexed.  This test is
+performed when an index is built (via the Git pack-index command), but
+a byte-by-byte comparison was deemed too computationally expensive to
+use in all circumstances: with pack files in particular, simply
+extracting an object can require not only decompressing it, but
+handling a series of delta encodings.
+
+Collision detection has been extended by computing a message digest of
+the object's contents (i.e., excluding the Git header). These message
+digests are stored separately from Git objects and are used for an
+independent collision test - looking up the message digests using the
+SHA-1 IDs as a key can be done quickly, and comparing them is fast as
+well (the digests are aligned to allow 32-bit or 64-bit integer
+comparisions).  This extension is computationally cheap (timing the
+Git test suite (run via 'make test') showed only a small increase in
+running time and the extension is backwards compatible with existing
+Git repositories - if a MD is not available for a SHA-1 value, the
+implementation reverts to its former behavior and simply compares
+SHA-1 values.  The implementation allows message digests to be easily
+added.
+
+The implementation creates a directory in .git/objects named "mdsd",
+which contains sub-directories and file names identical to the
+sub-directories in objects used to store loose objects: a two
+character directory name, with a 38-character file name, the
+concatenation of which gives the SHA-1 hash for the object.  the files
+in sub-directories of "mdsd", however, simply contain a one-byte code
+indicating the type of message digest, followed by the digest in its
+binary representation as a sequence of bytes.  In addition, for each
+pack file (.../objects/pack/FILE.pack), there is a corresponding file
+named .../objects/pack/FILE.mds in addition to
+.../objects/pack/FILE.idx.  The MDS file contains the MDs, stored in
+the same order as the SHA-1 hashes in .../objects/pack/FILE.idx.  The
+format of the MDS file is described in pack-format.txt.
+
+Thus, the directory structure (only part of it is shown) is as
+follows:
+
+ .git---.
+	|
+	|-objects-.
+	|	  |--XX--.
+	.	  |	 |--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+	.	  |	 .
+	.	  |	 .
+		  |	 .
+		  .
+		  .
+		  .
+		  |-mdsd-.
+		  |	 |--XX--.
+		  |	 |	|--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+		  |	 .	.
+		  |	 .	.
+		  |	 .	.
+		  |
+		  |-pack-.
+		  |	 |--YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.pack
+		  |	 |--YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.idx
+		  |	 |--YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.mds
+		  |	 .
+		  |	 .
+		  |	 .
+		  |
+		  `-info-.
+			 .
+			 .
+
+The mds files are relatively short - an average of N+1 bytes per MD
+of length N (provided N is a multiple of 4)
+plus some fixed overhead due to a header and trailer, with the MDs
+listed in the same order as the SHA-1 values in the matching idx file
+(a function named nth_packed_object_digest has the same signature as
+the previously-defined function nth_packed_object_offset, so the
+procedure to look up the MD value from a pack file is the same).
+
+For fetch and push operations, the commands fetch-pack, send-pack,
+receive-pack, and upload-pack were modified so that various object IDs
+can have any one of the following formats, with each number
+represented in hexadecimal:
+
+		SHA1
+		SHA1-MD
+
+where SHA1 is the SHA-1 hash of a commit and MD the message digest
+(prefixed by a code indicating the type of digest) of the commit
+(uncompressed, not including the Git object header).
+
+Both receive-pack and upload-pack send a capability named "mds-check"
+to allow the two longer object IDs.  When the MDs are available, the
+longer formats are used, but are generated only by fetch-pack and
+send-pack: because of backwards-compatibility constraints,
+receive-pack and upload-pack cannot determine the capabilities of
+fetch-pack and send-pack when connected to a remote repository).  The
+collision checks during a fetch, push, or pull command are done by
+receive-pack and upload pack because send-pack and fetch-pack do not
+receive their peers' MD values - send-pack and fetch-pack cannot determine
+their peers' capabilities given the current design.
+
+Changes to the Commit Format
+----------------------------
+
+A new header is available, positioned as the last header. It's name is
+"digest" and its value is a hex representation of a message digest in
+which the first two bytes name the algorithm used to generate the
+digest and the remaining bytes are the digest itself.  This digest is
+a digest of other digests or SHA-1 values.  It starts by including the
+digests of each object in the commit's tree with the exception of a
+commit from a submodule - in that case, the SHA-1 value itself is
+used.  The tree is searched depth first, including the tree's root,
+which provides the first digest.  This is followed by the digest for
+each parent commit in the order listed in the commit.  Finally, the
+digest covers the author, committer, encoding, and the commit message,
+all excluding the terminating newline character in the header.
+
+Note that the digest header complicates any attempt at generate a hash
+collision for a commit message - if you change a field, you also have
+to change the digest in a specific way.
+
+Configuration
+-------------
+
+There are several variables in the Makefile:
+
+      * MDSDB should have the value 0. If an alternative implementation
+	is defined, other values will be available.
+
+      * MDIGEST_DEFAULT should be defined to explicitly set the
+	default message digest.
+
+      * PACKDB should be defined to turn on the packdb functions.
+
+      * PACKDB_TEST should be defined only for debugging.  It uses some
+	packdb functions where not necessary to verify that these work
+	properly.  Turning this test on decreases performance.
+
+      * COMMIT_DIGEST should be defined to add a digest header to
+	commit messages as described above
+
+      * COMMIT_DIGEST_TEST should be defined to force commit_tree to
+	compute the digest even when COMMIT_DIGEST is undefined, in
+	which case the digest will be computed but not included in a
+	commit.
+
+Key Functions
+-------------
+
+For general use, the functions documented in mdigest.h can extract
+data from message digests and compare them.  The function verify_commit
+will test a commit to make sure that its digest field matches the
+repository.  The function has_sha1_file_digest allows one to determine
+if a digest exists and obtain a copy of that digest.
+
+To find functions that are used in the implementation (e.g., if changes
+to the pack-file format become necessary), search for the type
+mdigest_t or variables width digest in their names (e.g., digestp).
+
+
+Implementation Details
+----------------------
+
+Functions to manipulate the message digest/MD database are declared
+in the file mdsdb.h.  The implementation as described above is in the
+file objd-mdsdb.c: it is thus easy to change the implementation of how
+these objects are stored with minimal impact on the rest of the source
+code.  The message digest structure and functions to manipulate it are
+declared in mdigest.h, with the implementation in mdigest.c.
+
+In pack-write.c, there is a new function named write_mds_file with the
+same function signature as write_idx_file.  Both are called in pairs
+(write_idx_file first) so that the idx file and mds file for the
+corresponding pack file will always be created.
+
+In commit.c, there is a new function that recursively traverses the
+tree associated with a commit and finds the "blob" entries and looks
+up those entries' message digests in order to compute a message digest
+of these message digests (which is faster than computing a message
+digest of all the bytes in the blobs associated with a commit).
+
+Various function names signatures in sha1_file.c were changed to take
+two additional arguments, the first a pointer to an int used as a flag
+to indicate whether a MD exists, and the second a pointer to a
+uint32_t containing the MD.  For backwards compatibility with
+previously existing functions, those functions had there names changed
+by adding "_extended" to them, with macros in cache.h defined so that
+existing code that does not need to obtain a MD would not be
+changed. There are a few additional functions added to sha1_file.c
+such as one to determine if there is an MD for a given SHA-1
+value. Many changes in the rest of Git that result from this simply
+change the arguments to these functions.  As a convention, most such
+arguments use names like objcrc32, objcrc32p, has_objcrc32 and
+has_objcrc32p in order to make it easy to find areas of the code
+implementing hash-collision detection using the git-grep command.
+
+A few data structures (notably struct pack_idx_entry and struct
+packed_git) contain fields used to store has_objcrc32 and objcrc32
+values or data associated with MDS files.  These are used while
+building new MDS files.
+
+Some of the Git commands (count-objects, index-pack, and verify-pack)
+have additional command-line options related to the MDs and mds
+files. This makes it possible to explicitly name an mds file being
+created and to request that various listings show both the MD
+values in addition to SHA-1 hashes (the MD values are not listed
+by default in case user-defined scripts assume the current behavior).
+
+For C files, changes were made to the following files (compared to
+commit f56564968 - v1.7.8-rc4) for the initial collision-detection
+implementation:
+
+       * builtin/count-objects.c
+       * builtin/fetch-pack.c
+       * builtin/index-pack.c
+       * builtin/init-db.c
+       * builtin/pack-objects.c
+       * builtin/pack-redundant.c
+       * builtin/prune-packed.c
+       * builtin/prune.c
+       * builtin/receive-pack.c
+       * builtin/send-pack.c
+       * builtin/verify-pack.c
+       * commit.c
+       * environment.c
+       * fast-import.c
+       * gdbm-packdb.c (new file)
+       * git.c
+       * hex.c
+       * http.c
+       * mdigest.c (new file)
+       * objd-mdsdb.c (new file)
+       * pack-write.c
+       * sha1_file.c
+       * upload-pack.c
+
+The other files had changes that reflected changes to function
+signatures.
+
+The header files that were modified are
+
+    * cache.h
+    * commit.h
+    * mdigest.h (new file)
+    * mdsdb.h (new file)
+    * pack.h
+    * packdb.h (new file)
+
+where the changes are mostly new function declarations, a few macros
+for backwards-compatibility, and a few additional fields in some
+data structures.
+
+Minor changes were made to the test suite: t0000-basic.sh,
+t5300-pack-object.sh, t5304-prune.sh, t5500-fetch-pack.sh, and
+t5510-fetch.sh.
+
+The packdb functions are conditionally compiled and by default are not
+used.  When used, these use GDBM to store MDs for SHA-1 hashes in
+cases in which the hash was not available - in this case the hash will
+be recomputed and stored for future use.  Testing indicates that
+packdb is not needed. It may be worth turning on during debugging to
+verify if a problem is discovered involving a missing MD. (As an
+aside, the packdb code is based on a test to see if GDBM would be
+efficient enough to store the MD values in general, thus avoiding
+the need to create "mds" files and reducing the number of files in the
+"mdsd" directory, but it turned out that performance was not
+acceptable.)
+
+Security-Issue Details
+----------------------
+
+Without hash-collision detection, Git has a possible risk of data
+corruption due to the obvious hash-collision vulnerability, so the
+issue is really whether a usable vulnerability exists. In the case
+of a single shared repository (one common repository shared by
+multiple developers), this risk is mitigated by Git's rule that
+an existing entry is never overridden. The situation is more complex
+when multiple repositories are used, as a race condition may exist.
+Also, the risk depends on whether or not developers exchange source
+files by some out-of-band mechanism (e.g., email) - when programming
+in Java, for example, it is customary to use the javadocs program to
+create API documentation from stylized comments in source files. A
+programmer might send a peer a copy of a source file and to review
+and correct the java-doc comments, providing an opporunity for the
+second developer to insert a modified file into the respository. The
+first developer would presumably check that the source code has not
+changed (an automated test for this might use the java compiler's
+"-g:none" option so that line-number data does not appear in the object
+file), and review the comments, but would not care about formatting
+(location of line breaks, etc., as the javadocs program generates HTML).
+
+In any event, recent research has shown that SHA-1 collisions can be
+found in 2^63 operations or less.  While one result claimed 2^53
+operations, the paper claiming that value was withdrawn from
+publication due to an error in the estimate. Another result claimed a
+complexity of between 2^51 and 2^57 operations, and still another
+claimed a complexity of 2^57.5 SHA-1 computations. A summary is
+available at
+<http://hackipedia.org/Checksums/SHA/html/SHA-1.htm#SHA-1>.
+This is within or close to the number of computations that can be
+managed by a well-funded organization.
diff --git a/Documentation/technical/pack-format.txt b/Documentation/technical/pack-format.txt
index 1803e64..a2aad5f 100644
--- a/Documentation/technical/pack-format.txt
+++ b/Documentation/technical/pack-format.txt
@@ -158,3 +158,50 @@ Pack file entry: <+
     corresponding packfile.
 
     20-byte SHA1-checksum of all of the above.
+
+
+= pack-*.mds files contain message digests for objects.  The digests
+  are stored in the same order as the sha-1 values in the matching idx
+  file.  These files have the following format:
+
+  - A 6-byte magic number consisting the the characters "PKMDS" followed
+    by a NULL character (0).
+
+  - A one-byte version number (= 1)
+
+  - A one-byte field-length value for message digest fields, in units
+    of 4-byte words.  (The length of the message digest fields in bytes
+    is denoted as wbsize below)
+
+  - A set of blocks, each of which contains 4 entries encoded as follows:
+
+      * four one-byte fields (wcode fields), one per entry, for which
+	a zero value indicates that a matching entry does not exist
+	and a non-zero value indicates the type of message digest
+	encoded as follows:
+
+	   + 1 for a CRC  (used as a trivial case for performance testing)
+
+	   + 5 for SHA-1
+
+	   + 8 for SHA-256
+
+	   + 16 for SHA-512
+
+      * 4 wbsize-byte fields, each containing a message digest (by
+	convention which must be all NULL characters if the MD does
+	not exist).  For each field, the data it contains should start
+	at the first byte, padded with NULL characters if the field is
+	longer than the digest it stores.
+
+    For the set of all blocks, the nth one-byte field and the nth
+    wcode field store the values for the nth entry in the
+    file. The format ensures that each message digest starts on a
+    32-bit boundary, allowing 32-bit integer operations to be used in
+    copying or comparing values.
+
+  - A 20 byte SHA-1 hash of the SHA-1 hashes naming the objects whose
+    message digests are being stored, in the same order as they
+    appear in the corresponding idx file.
+
+  - A 20 byte SHA-1 hash of all of the above.
-- 
1.7.1

^ permalink raw reply related

* Patches for message-digest support.
From: Bill Zaumen @ 2011-12-21  7:51 UTC (permalink / raw)
  To: git, peff, pclouds, gitster


I just sent a series of 6 patches, roughly similar to the ones I sent a
few weeks ago, but allowing a choice of message digests in addition to
a CRC (kept for testing purposes) - SHA-1, SHA-256, and SHA-512 with
more added easily.  The current default is SHA-256.  The use of SHA-1
for git object IDs is unchanged. Unlike the object-ID digest, the
additional digests do not include the Git object-header.  I also changed
a number of function names, using "digest" or "mdigest" in them.
Searching for the string "digest" is a good way of finding things.
Finally, I added a header to commit messages (conditionally compiled so
this can be turned off) that contains a digest of digests plus some
other fields.  I also broke it up into a series of smaller patches.

Just as a summary:

The first patch contains several new files.  It uses a data structure
for message digests that keeps the bytes of a digest aligned on
32 or 64 bit boundaries to allow fast comparisons. The digests are
stored long with a one-byte code indicating the digest type. The code
handles storing and looking up the digests, including support for
alternate object databases.

The second patch modifies some of the existing git files (the major
changes are in sha1_file.c and pack-write.c) for storing message digests
when an object or a pack index file is created.

The third patch modifies the files in the builtin directory that contain
the implementation of git commands for packing and pruning objects, and
for verifying pack files and counting objects.  The code does some
checks for hash collisions by comparing the digests.  At this point,
each git object will have a digest that can be looked up given the
object's ID.  This mapping is maintained as pack files are
created.

The fourth patch adds a digest header to commit messages.  This header
contains a digest of the digests for the commit's parents and for each
object in the commit's tree, and of the other fields in the commit.
The digest header, like the rest of the commit, is used in computing the
commit's object ID and matching digest.  A function verify_commit
checks the digest header by recomputing it and can be used as desired
for authentication or other purposes.

The fifth patch transfers the message digest corresponding to a SHA-1
ID during fetch or push operations to allow early detection of
collisions.  This is a fast test - a simple lookup - and can be turned
off by removing the "mds-check" capability.

The sixth patch contains documentation.

Bill

^ permalink raw reply

* Re: [PATCH] Use Python's "print" as a function, not as a keyword
From: Frans Klaver @ 2011-12-21  8:43 UTC (permalink / raw)
  To: Sebastian Morr; +Cc: git, srabbelier, Ævar Arnfjörð Bjarmason
In-Reply-To: <20111221021930.GA31364@thinkpad>

On Wed, Dec 21, 2011 at 3:19 AM, Sebastian Morr <sebastian@morr.cc> wrote:

> This has changed from Version 2.6 to Version 3.0. Replace all occurrences of
>
>    print ...
>
> with
>
>    print(...)
>
> and all occurrences of
>
>    print >> output, ...
>
> with
>
>    output.write(... + "\n")

While it's good to look forward, you shouldn't forget about testing on
python 2.6. Lots of people still stick to that and maybe even to
earlier versions.


>  if len(argv) < 2:
> -       print 'Usage:', argv[0], '<zipfile>...'
> +       print('Usage:', argv[0], '<zipfile>...')
>        exit(1)
>

Here I would use the % notation:
print('Usage: %s <zipfile>...' % argv[0])

Python 2.x would print a tuple:

>>> argv = ('import-zips.py',)
>>> print("Usage:", argv[0], '<zipfile>...')
('Usage:', 'import-zips.py', '<zipfile>...')

You could probably get away with

print('Usage: ' + argv[0] + ' <zipfile>...')

But that could probably become a readability issue. I would even
wonder if it's considered pythonic.

It happens a few times more:

>  if verbose:
> -    print 'tip is', tip
> +    print('tip is', tip)

> @@ -176,27 +176,27 @@ for cset in range(int(tip) + 1):
>     os.write(fdcomment, csetcomment)
>     os.close(fdcomment)
>
> -    print '-----------------------------------------'
> -    print 'cset:', cset
> -    print 'branch:', hgbranch[str(cset)]
> -    print 'user:', user
> -    print 'date:', date
> -    print 'comment:', csetcomment
> +    print('-----------------------------------------')
> +    print('cset:', cset)
> +    print('branch:', hgbranch[str(cset)])
> +    print('user:', user)
> +    print('date:', date)
> +    print('comment:', csetcomment)
>     if parent:
> -       print 'parent:', parent
> +       print('parent:', parent)
>     if mparent:
> -        print 'mparent:', mparent
> +        print('mparent:', mparent)
>     if tag:
> -        print 'tag:', tag
> -    print '-----------------------------------------'
> +        print('tag:', tag)
> +    print('-----------------------------------------')


>
>     # checkout the parent if necessary
>     if cset != 0:
>         if hgbranch[str(cset)] == "branch-" + str(cset):
> -            print 'creating new branch', hgbranch[str(cset)]
> +            print('creating new branch', hgbranch[str(cset)])
>             os.system('git checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))
>         else:
> -            print 'checking out branch', hgbranch[str(cset)]
> +            print('checking out branch', hgbranch[str(cset)])
>             os.system('git checkout %s' % hgbranch[str(cset)])
>
>     # merge
> @@ -205,7 +205,7 @@ for cset in range(int(tip) + 1):
>             otherbranch = hgbranch[mparent]
>         else:
>             otherbranch = hgbranch[parent]
> -        print 'merging', otherbranch, 'into', hgbranch[str(cset)]
> +        print('merging', otherbranch, 'into', hgbranch[str(cset)])
>         os.system(getgitenv(user, date) + 'git merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch))
>
>     # remove everything except .git and .hg directories
> @@ -229,12 +229,12 @@ for cset in range(int(tip) + 1):
>
>     # delete branch if not used anymore...
>     if mparent and len(hgchildren[str(cset)]):
> -        print "Deleting unused branch:", otherbranch
> +        print("Deleting unused branch:", otherbranch)
>         os.system('git branch -d %s' % otherbranch)
>
>     # retrieve and record the version
>     vvv = os.popen('git show --quiet --pretty=format:%H').read()
> -    print 'record', cset, '->', vvv
> +    print('record', cset, '->', vvv)
>     hgvers[str(cset)] = vvv
>
>  if hgnewcsets >= opt_nrepack and opt_nrepack != -1:
> @@ -243,7 +243,7 @@ if hgnewcsets >= opt_nrepack and opt_nrepack != -1:
>  # write the state for incrementals
>  if state:
>     if verbose:
> -        print 'Writing state'
> +        print('Writing state')
>     f = open(state, 'w')
>     pickle.dump(hgvers, f)
>
> diff --git a/contrib/p4import/git-p4import.py b/contrib/p4import/git-p4import.py
> index b6e534b..144fafc 100644
> --- a/contrib/p4import/git-p4import.py
> +++ b/contrib/p4import/git-p4import.py
> @@ -26,11 +26,11 @@ if s != default_int_handler:
>  def die(msg, *args):
>     for a in args:
>         msg = "%s %s" % (msg, a)
> -    print "git-p4import fatal error:", msg
> +    print("git-p4import fatal error:", msg)
>     sys.exit(1)
>

I think that's it for the print(...,...) stuff. I might have misssed
one or two though.


> diff --git a/git-remote-testgit.py b/git-remote-testgit.py
> index 3dc4851..9803214 100644
> --- a/git-remote-testgit.py
> +++ b/git-remote-testgit.py
> @@ -81,9 +81,9 @@ def do_capabilities(repo, args):
>     """Prints the supported capabilities.
>     """
>
> -    print "import"
> -    print "export"
> -    print "refspec refs/heads/*:%s*" % repo.prefix
> +    print("import")
> +    print("export")
> +    print("refspec refs/heads/*:%s*" % repo.prefix)
>
>     dirname = repo.get_base_path(repo.gitdir)
>
> @@ -92,11 +92,11 @@ def do_capabilities(repo, args):
>
>     path = os.path.join(dirname, 'testgit.marks')
>
> -    print "*export-marks %s" % path
> +    print("*export-marks %s" % path)
>     if os.path.exists(path):
> -        print "*import-marks %s" % path
> +        print("*import-marks %s" % path)
>
> -    print # end capabilities
> +    print() # end capabilities

print("") here. 2.x:

>>> print()
()



>
>
>  def do_list(repo, args):
> @@ -109,16 +109,16 @@ def do_list(repo, args):
>
>     for ref in repo.revs:
>         debug("? refs/heads/%s", ref)
> -        print "? refs/heads/%s" % ref
> +        print("? refs/heads/%s" % ref)
>
>     if repo.head:
>         debug("@refs/heads/%s HEAD" % repo.head)
> -        print "@refs/heads/%s HEAD" % repo.head
> +        print("@refs/heads/%s HEAD" % repo.head)
>     else:
>         debug("@refs/heads/master HEAD")
> -        print "@refs/heads/master HEAD"
> +        print("@refs/heads/master HEAD")
>
> -    print # end list
> +    print() # end list

print("")

Lots more to do, I'm afraid.

Cheers,
Frans

^ permalink raw reply

* Re: [PATCH] Specify a precision for the length of a subject string
From: Andreas Schwab @ 2011-12-21 11:26 UTC (permalink / raw)
  To: Nathan W. Panike; +Cc: git
In-Reply-To: <20111220220754.GC21353@llunet.cs.wisc.edu>

"Nathan W. Panike" <nathan.panike@gmail.com> writes:

> $ git log --pretty='%h %30s' d165204 -1

In C's formatted output this syntax denotes a minimum field width, not a
precision, so it will probably be surprising to many people.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* [PATCH] builtin/log: remove redundant initialization
From: Michael Schubert @ 2011-12-21 12:05 UTC (permalink / raw)
  To: git

"abbrev" and "commit_format" in struct rev_info get initialized in
init_revisions - no need to reinit in cmd_log_init_defaults.

Signed-off-by: Michael Schubert <mschub@elegosoft.com>
---
 builtin/log.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/builtin/log.c b/builtin/log.c
index 89d0cc0..7d1f6f8 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -73,8 +73,6 @@ static int decorate_callback(const struct option *opt, const char *arg, int unse
 
 static void cmd_log_init_defaults(struct rev_info *rev)
 {
-	rev->abbrev = DEFAULT_ABBREV;
-	rev->commit_format = CMIT_FMT_DEFAULT;
 	if (fmt_pretty)
 		get_commit_format(fmt_pretty, rev);
 	rev->verbose_header = 1;
-- 
1.7.8.400.g03f4

^ permalink raw reply related

* Re: Escape character for .gitconfig
From: Peter Krefting @ 2011-12-21 12:54 UTC (permalink / raw)
  To: Erik Blake; +Cc: Git Mailing List
In-Reply-To: <4EEC6A9D.1060005@icefield.yk.ca>

Erik Blake:

> As you can see, I'm running git on a Win7 64 machine. Is there any way to 
> escape the brackets? Or do I need to reinstall notepad++ on a different path?

Just use the 8.3 path instead, using either "C:/Progra~1" or "C:/Progra~2" 
(depending on how the system got installed). You can mix 8.3 and long paths 
in the same command (so keeping the "Notepad++" component is fine).

-- 
\\// Peter - http://www.softwolves.pp.se/

^ permalink raw reply

* Re: Rewriting history and public-private-ish branches
From: Peter Krefting @ 2011-12-21 12:58 UTC (permalink / raw)
  To: Jay Levitt; +Cc: git@vger.kernel.org
In-Reply-To: <4EF08086.6080606@gmail.com>

Jay Levitt:

> As long as I'm the only one who's seen this "published" history, am I doing 
> anything bad?

I do things like that too, and as long as you know what you are doing, it 
usually works fine.

> Do I leave any residue behind in the repo?

As long as you run "git gc" on the repos regularly, it shouldn't really 
matter much. Your abandoned changes will be available through the reflog 
until that expires, and when that has happened "git gc" should remove them 
from the repositories altogether.

-- 
\\// Peter - http://www.softwolves.pp.se/

^ permalink raw reply

* Re: Escape character for .gitconfig
From: demerphq @ 2011-12-21 13:59 UTC (permalink / raw)
  To: Peter Krefting; +Cc: Erik Blake, Git Mailing List
In-Reply-To: <alpine.DEB.2.00.1112211352580.17957@ds9.cixit.se>

On 21 December 2011 13:54, Peter Krefting <peter@softwolves.pp.se> wrote:
> Erik Blake:
>
>
>> As you can see, I'm running git on a Win7 64 machine. Is there any way to
>> escape the brackets? Or do I need to reinstall notepad++ on a different
>> path?
>
>
> Just use the 8.3 path instead, using either "C:/Progra~1" or "C:/Progra~2"
> (depending on how the system got installed). You can mix 8.3 and long paths
> in the same command (so keeping the "Notepad++" component is fine).

Or use a junction to make an alias of the name without strange chars....

Yves


-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

^ permalink raw reply

* Re: [PATCH] Specify a precision for the length of a subject string
From: Nathan Panike @ 2011-12-21 14:51 UTC (permalink / raw)
  To: Jeff King; +Cc: Nathan W. Panike, git
In-Reply-To: <20111221043843.GA20714@sigill.intra.peff.net>

On Tue, Dec 20, 2011 at 11:38:43PM -0500, Jeff King wrote:
> On Tue, Dec 20, 2011 at 04:07:54PM -0600, Nathan W. Panike wrote:
> 
> > We can specify the precision of a subject string, so that length the subjects
> > viewed by the user do not grow beyond a bound set by the user, in a pretty
> > formatted string
> > 
> > This makes it possible to do, e.g., 
> > 
> > $ git log --pretty='%h %s' d165204 -1
> > d165204 git-p4: fix skipSubmitEdit regression
> > 
> > With this patch, the user can do
> > 
> > $ git log --pretty='%h %30s' d165204 -1
> > d165204 git-p4: fix skipSubmitEdit reg
> 
> Hmm. I think the idea of limiting is OK (though personally, I would just
> pipe through a filter that truncates long lines). But I'm a bit negative
> on adding a tweak like this that only affects the subject. Is there a
> reason I couldn't do %30gs, or %30f, or even some other placeholder?

The ones that make sense to limit are all those that depend on the subject, as the
above; it does not make sense to limit other fields that don't depend on the
subject, as they are fixed width, or have small variance. And it does not make
sense to me to limit the length of the body.

> 
> Also, we already have %w to handle wrapping. Could this be handled in a
> similar way (perhaps it could even be considered a special form of
> wrapping)?

I'll look at the wrapping code and see. Thanks for the idea.
> 
> -Peff

^ permalink raw reply

* Re: [PATCH] Specify a precision for the length of a subject string
From: Nathan Panike @ 2011-12-21 14:53 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Nathan W. Panike, git
In-Reply-To: <m2liq6go7y.fsf@igel.home>

On Wed, Dec 21, 2011 at 12:26:25PM +0100, Andreas Schwab wrote:
> "Nathan W. Panike" <nathan.panike@gmail.com> writes:
> 
> > $ git log --pretty='%h %30s' d165204 -1
> 
> In C's formatted output this syntax denotes a minimum field width, not a
> precision, so it will probably be surprising to many people.

C semantics are already broken because (from git-log(1))

"If you add a - (minus sign) after % of a placeholder, line-feeds that
immediately precede the expansion are deleted if and only if the placeholder
expands to an empty string."

rather than indicating justification of the field.
> 
> Andreas.
> 
> -- 
> Andreas Schwab, schwab@linux-m68k.org
> GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
> "And now for something completely different."

^ permalink raw reply

* [PATCH] builtin/commit: add missing '/' in help message
From: Michael Schubert @ 2011-12-21 14:56 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

Signed-off-by: Michael Schubert <mschub@elegosoft.com>
---
 builtin/commit.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 626036a..be1ab2e 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -139,7 +139,7 @@ static struct option builtin_commit_options[] = {
 	OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
 	OPT_STRING(0, "fixup", &fixup_message, "commit", "use autosquash formatted message to fixup specified commit"),
 	OPT_STRING(0, "squash", &squash_message, "commit", "use autosquash formatted message to squash specified commit"),
-	OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
+	OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C/-c/--amend)"),
 	OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
 	OPT_FILENAME('t', "template", &template_file, "use specified template file"),
 	OPT_BOOL('e', "edit", &edit_flag, "force edit of commit"),
-- 
1.7.8.521.g64725

^ permalink raw reply related

* [PATCH] git-commit: add option --date-now
From: Michael Schubert @ 2011-12-21 14:56 UTC (permalink / raw)
  To: git

Currently, Git doesn't provide an easy way to use the current date when
amending a commit or reusing an existing commmit with -C/-c. Therefore,
add --date-now.

Signed-off-by: Michael Schubert <mschub@elegosoft.com>
---
 Documentation/git-commit.txt |    7 +++++--
 builtin/commit.c             |    9 ++++++++-
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 5cc84a1..b7c6f0d 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -12,8 +12,8 @@ SYNOPSIS
 	   [--dry-run] [(-c | -C | --fixup | --squash) <commit>]
 	   [-F <file> | -m <msg>] [--reset-author] [--allow-empty]
 	   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
-	   [--date=<date>] [--cleanup=<mode>] [--status | --no-status]
-	   [-i | -o] [--] [<file>...]
+	   [--date=<date> | --date-now] [--cleanup=<mode>]
+	   [--status | --no-status] [-i | -o] [--] [<file>...]
 
 DESCRIPTION
 -----------
@@ -126,6 +126,9 @@ OPTIONS
 --date=<date>::
 	Override the author date used in the commit.
 
+--date-now
+	Override the author date used in the commit with the current local time.
+
 -m <msg>::
 --message=<msg>::
 	Use the given <msg> as the commit message.
diff --git a/builtin/commit.c b/builtin/commit.c
index be1ab2e..28fdf1a 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -82,6 +82,7 @@ static const char *author_message, *author_message_buffer;
 static char *edit_message, *use_message;
 static char *fixup_message, *squash_message;
 static int all, also, interactive, patch_interactive, only, amend, signoff;
+static int date_now;
 static int edit_flag = -1; /* unspecified */
 static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
 static int no_post_rewrite, allow_empty_message;
@@ -134,6 +135,7 @@ static struct option builtin_commit_options[] = {
 	OPT_FILENAME('F', "file", &logfile, "read message from file"),
 	OPT_STRING(0, "author", &force_author, "author", "override author for commit"),
 	OPT_STRING(0, "date", &force_date, "date", "override date for commit"),
+	OPT_BOOLEAN(0, "date-now", &date_now, "override date for commit with current local time"),
 	OPT_CALLBACK('m', "message", &message, "message", "commit message", opt_parse_m),
 	OPT_STRING('c', "reedit-message", &edit_message, "commit", "reuse and edit message from specified commit"),
 	OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
@@ -557,7 +559,9 @@ static void determine_author_info(struct strbuf *author_ident)
 					(lb - strlen(" ") -
 					 (a + strlen("\nauthor "))));
 		email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
-		date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
+		if (!date_now)
+			date = xmemdupz(rb + strlen("> "),
+					eol - (rb + strlen("> ")));
 	}
 
 	if (force_author) {
@@ -1018,6 +1022,9 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (force_author && renew_authorship)
 		die(_("Using both --reset-author and --author does not make sense"));
 
+	if (force_date && date_now)
+		die(_("Using both --date and --date-now does not make sense"));
+
 	if (logfile || message.len || use_message || fixup_message)
 		use_editor = 0;
 	if (0 <= edit_flag)
-- 
1.7.8.521.g64725

^ permalink raw reply related

* Re: [PATCH] git-commit: add option --date-now
From: Carlos Martín Nieto @ 2011-12-21 15:38 UTC (permalink / raw)
  To: Michael Schubert; +Cc: git
In-Reply-To: <4EF1F3AB.5080607@elegosoft.com>

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

On Wed, Dec 21, 2011 at 03:56:43PM +0100, Michael Schubert wrote:
> Currently, Git doesn't provide an easy way to use the current date when
> amending a commit or reusing an existing commmit with -C/-c. Therefore,
> add --date-now.

The option --reset-author also resets the date. So 'git commit
--ammend --reset-author' does what 'git commit --amend --date-now'
would do in most cases. I was surpised when I tried 'git commit
--amend --date=now' that git didn't understand 'now' as a date, which
seems like a more obvious place to fix it.

> 
> Signed-off-by: Michael Schubert <mschub@elegosoft.com>
> ---
>  Documentation/git-commit.txt |    7 +++++--
>  builtin/commit.c             |    9 ++++++++-
>  2 files changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
> index 5cc84a1..b7c6f0d 100644
> --- a/Documentation/git-commit.txt
> +++ b/Documentation/git-commit.txt
> @@ -12,8 +12,8 @@ SYNOPSIS
>  	   [--dry-run] [(-c | -C | --fixup | --squash) <commit>]
>  	   [-F <file> | -m <msg>] [--reset-author] [--allow-empty]
>  	   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
> -	   [--date=<date>] [--cleanup=<mode>] [--status | --no-status]
> -	   [-i | -o] [--] [<file>...]
> +	   [--date=<date> | --date-now] [--cleanup=<mode>]
> +	   [--status | --no-status] [-i | -o] [--] [<file>...]
>  
>  DESCRIPTION
>  -----------
> @@ -126,6 +126,9 @@ OPTIONS
>  --date=<date>::
>  	Override the author date used in the commit.
>  
> +--date-now
> +	Override the author date used in the commit with the current local time.
> +
>  -m <msg>::
>  --message=<msg>::
>  	Use the given <msg> as the commit message.
> diff --git a/builtin/commit.c b/builtin/commit.c
> index be1ab2e..28fdf1a 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -82,6 +82,7 @@ static const char *author_message, *author_message_buffer;
>  static char *edit_message, *use_message;
>  static char *fixup_message, *squash_message;
>  static int all, also, interactive, patch_interactive, only, amend, signoff;
> +static int date_now;
>  static int edit_flag = -1; /* unspecified */
>  static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
>  static int no_post_rewrite, allow_empty_message;
> @@ -134,6 +135,7 @@ static struct option builtin_commit_options[] = {
>  	OPT_FILENAME('F', "file", &logfile, "read message from file"),
>  	OPT_STRING(0, "author", &force_author, "author", "override author for commit"),
>  	OPT_STRING(0, "date", &force_date, "date", "override date for commit"),
> +	OPT_BOOLEAN(0, "date-now", &date_now, "override date for commit with current local time"),
>  	OPT_CALLBACK('m', "message", &message, "message", "commit message", opt_parse_m),
>  	OPT_STRING('c', "reedit-message", &edit_message, "commit", "reuse and edit message from specified commit"),
>  	OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
> @@ -557,7 +559,9 @@ static void determine_author_info(struct strbuf *author_ident)
>  					(lb - strlen(" ") -
>  					 (a + strlen("\nauthor "))));
>  		email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
> -		date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
> +		if (!date_now)
> +			date = xmemdupz(rb + strlen("> "),
> +					eol - (rb + strlen("> ")));
>  	}
>  
>  	if (force_author) {
> @@ -1018,6 +1022,9 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  	if (force_author && renew_authorship)
>  		die(_("Using both --reset-author and --author does not make sense"));
>  
> +	if (force_date && date_now)
> +		die(_("Using both --date and --date-now does not make sense"));
> +
>  	if (logfile || message.len || use_message || fixup_message)
>  		use_editor = 0;
>  	if (0 <= edit_flag)
> -- 
> 1.7.8.521.g64725
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* [PATCH] bash completion: use read -r everywhere
From: Thomas Rast @ 2011-12-21 15:54 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Kevin Ballard

POSIX specifies

  The read utility shall read a single line from standard input.
  By default, unless the -r option is specified, backslash ('\')
  shall act as an escape character...

Our omission of -r breaks the loop reading refnames from
git-for-each-ref in __git_refs() if there are refnames such as
"foo'bar", in which case for-each-ref helpfully quotes them as in

  $ git update-ref "refs/remotes/test/foo'bar" HEAD
  $ git for-each-ref --shell --format="ref=%(refname:short)" "refs/remotes"
  ref='test/foo'\''bar'

Interpolating the \' here will read "ref='test/foo'''bar'" instead,
and eval then chokes on the unbalanced quotes.

However, since none of the read loops _want_ to have backslashes
interpolated, it's much safer to use read -r everywhere.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 contrib/completion/git-completion.bash |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 78257ae..e7a39ef 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -111,7 +111,7 @@ __git_ps1_show_upstream ()
 
 	# get some config options from git-config
 	local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
-	while read key value; do
+	while read -r key value; do
 		case "$key" in
 		bash.showupstream)
 			GIT_PS1_SHOWUPSTREAM="$value"
@@ -589,7 +589,7 @@ __git_refs ()
 			local ref entry
 			git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \
 				"refs/remotes/" | \
-			while read entry; do
+			while read -r entry; do
 				eval "$entry"
 				ref="${ref#*/}"
 				if [[ "$ref" == "$cur"* ]]; then
@@ -602,7 +602,7 @@ __git_refs ()
 	case "$cur" in
 	refs|refs/*)
 		git ls-remote "$dir" "$cur*" 2>/dev/null | \
-		while read hash i; do
+		while read -r hash i; do
 			case "$i" in
 			*^{}) ;;
 			*) echo "$i" ;;
@@ -611,7 +611,7 @@ __git_refs ()
 		;;
 	*)
 		git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \
-		while read hash i; do
+		while read -r hash i; do
 			case "$i" in
 			*^{}) ;;
 			refs/*) echo "${i#refs/*/}" ;;
@@ -636,7 +636,7 @@ __git_refs_remotes ()
 {
 	local i hash
 	git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \
-	while read hash i; do
+	while read -r hash i; do
 		echo "$i:refs/remotes/$1/${i#refs/heads/}"
 	done
 }
@@ -1863,7 +1863,7 @@ __git_config_get_set_variables ()
 	done
 
 	git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
-	while read line
+	while read -r line
 	do
 		case "$line" in
 		*.*=*)
-- 
1.7.8.484.gdad4270

^ permalink raw reply related

* Re: [PATCH] Use Python's "print" as a function, not as a keyword
From: Sverre Rabbelier @ 2011-12-21 16:12 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: Sebastian Morr, git
In-Reply-To: <CACBZZX7PVyCFfHTJN_QZfyt5wAcr4UAiJSmo54PSi=8pgv3sYA@mail.gmail.com>

On Tue, Dec 20, 2011 at 20:48, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:
> I'm running Debian unstable and it has Python 2.7. Most people are
> still using Python 2.x as their default system Python since 3.x breaks
> backwards compatibility for common constructs like print.
>
> Does this only break Python 2.6, or all 2.x versions of Python?
>
> What's our currently supported Python version for the Python code in
> Git? It's 5.8.0 for Perl, do we have any particular aim for a
> supported Python version?

Python 2.4.

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [PATCH] git-commit: add option --date-now
From: Matthieu Moy @ 2011-12-21 16:24 UTC (permalink / raw)
  To: Carlos Martín Nieto; +Cc: Michael Schubert, git
In-Reply-To: <20111221153837.GC2160@beez.lab.cmartin.tk>

Carlos Martín Nieto <cmn@elego.de> writes:

> I was surpised when I tried 'git commit --amend --date=now' that git
> didn't understand 'now' as a date, which seems like a more obvious
> place to fix it.

+1

I really don't think Git wants yet-another-option for each use-case we
find, and accepting "now" as a date (either by hardcoding "now" as an
accepted value, or by running approxidate on the argument of --date).

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

^ permalink raw reply

* Re: Re* How to generate pull-request with info of signed tag
From: Aneesh Kumar K.V @ 2011-12-21 16:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vzkemh0de.fsf@alter.siamese.dyndns.org>

On Tue, 20 Dec 2011 23:03:57 -0800, Junio C Hamano <gitster@pobox.com> wrote:
> "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> writes:
> 
> > Also can we make .git/config remote stanza to have something like below
> >
> >
> >      fetch = +refs/tags/*:refs/tags/abc/*
> >
> > so that one can do
> >
> >    git fetch t-remote tag-name
> >
> > and that get stored to abc/tag-name 
> 
> You can do whatever you want to your own config file without asking anybody.
> 
> Having said that, the point of the recent change to allow you to pull this
> way (notice the lack of "tag")
> 
>     $ git pull $url $signed_tag_name
> 
> is so that you do not have to contaminate your own ref namespace with tags
> that are used to leave audit trails in the history graph.
> 

With an entry like below

[remote "github"]
        fetch = +refs/tags/*:refs/tags/origin/*
        url = git://github.com/kvaneesh/QEMU.git

when i do git fetch github for-anthony i get the below error

[master@QEMU]$ git fetch github for-anthony
From git://github.com/kvaneesh/QEMU
 * tag               for-anthony -> FETCH_HEAD
[master@QEMU]$ less .git/config 

Also trying to do

[master@QEMU]$ git fetch git://github.com/kvaneesh/QEMU.git  for-anthony:aneesh/for-anthony
error: Trying to write non-commit object 12916047784615b7d8b879d9d39be6c1559e1b1b to branch refs/heads/aneesh/for-anthony
From git://github.com/kvaneesh/QEMU
 ! [new branch]      for-anthony -> aneesh/for-anthony  (unable to update local ref)
 * [new tag]         for-anthony -> for-anthony


I understand that replacing the above with below works. But we should
not be required to specify refs/tags there right ?

[master@QEMU]$ git fetch git://github.com/kvaneesh/QEMU.git  refs/tags/for-anthony:refs/tags/aneesh/for-anthony

-aneesh

^ permalink raw reply

* Re: git 1.7.7.5
From: Thomas Jarosch @ 2011-12-21 17:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jonathan Nieder, git, schacon
In-Reply-To: <7viplckt2m.fsf@alter.siamese.dyndns.org>

On Tuesday, 20. December 2011 01:03:29 Junio C Hamano wrote:
> but anyway I've uploaded both 1.7.7.5 and 1.7.6.5 tarballs.

Thanks!

May be Scott Chacon can provide you commit access to git-scm.com ;)
If you are interested in this of course.

For example wikipedia lists git-scm.com as website for git.
(http://en.wikipedia.org/wiki/Git_%28software%29)

Cheers,
Thomas

^ permalink raw reply

* [PATCH] clone: don't say <branch> when we mean <remote>
From: Carlos Martín Nieto @ 2011-12-21 18:14 UTC (permalink / raw)
  To: git

Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
---

The manpage says <name> which might actually be a better word to use
everywhere, but having <branch> instead of <remote> can only lead to
confusion.

Looking through blame, the second line survived a typo fix and was
introduced in 2008 when clone was made a builtin. The script used to
say <name>. So it's clearly nothing urgent, but it bugged me, so I'm
sending a patch.

 builtin/clone.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index efe8b6c..e85ee69 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -84,8 +84,8 @@ static struct option builtin_clone_options[] = {
 		   "directory from which templates will be used"),
 	OPT_CALLBACK(0 , "reference", &option_reference, "repo",
 		     "reference repository", &opt_parse_reference),
-	OPT_STRING('o', "origin", &option_origin, "branch",
-		   "use <branch> instead of 'origin' to track upstream"),
+	OPT_STRING('o', "origin", &option_origin, "remote",
+		   "use <remote> instead of 'origin' to track upstream"),
 	OPT_STRING('b', "branch", &option_branch, "branch",
 		   "checkout <branch> instead of the remote's HEAD"),
 	OPT_STRING('u', "upload-pack", &option_upload_pack, "path",
-- 
1.7.8.352.g876a6f

^ permalink raw reply related

* Re: [PATCH 4/4] Suppress "statement not reached" warnings under Sun Studio
From: Junio C Hamano @ 2011-12-21 18:27 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Elijah Newren, Jason Evans, David Barr
In-Reply-To: <1324430302-22441-5-git-send-email-avarab@gmail.com>

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> diff --git a/read-cache.c b/read-cache.c
> index a51bba1..0a4e895 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -758,7 +758,13 @@ int verify_path(const char *path)
>  		return 0;
>  
>  	goto inside;
> +#ifdef __sun
> +#	pragma error_messages (off, E_STATEMENT_NOT_REACHED)
> +#endif
>  	for (;;) {
> +#ifdef __sun
> +#	pragma error_messages (on, E_STATEMENT_NOT_REACHED)
> +#endif
>  		if (!c)
>  			return 1;

Patches 1-3 makes sense, but this one is too ugly to live.

Wouldn't something like this be equivalent and have the same effect
without sacrificing the readablity?

diff --git a/read-cache.c b/read-cache.c
index a51bba1..73af797 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -757,12 +757,12 @@ int verify_path(const char *path)
 	if (has_dos_drive_prefix(path))
 		return 0;
 
-	goto inside;
+	/* we are at the beginning of a path component */
+	c = '/';
 	for (;;) {
 		if (!c)
 			return 1;
 		if (is_dir_sep(c)) {
-inside:
 			c = *path++;
 			if ((c == '.' && !verify_dotfile(path)) ||
 			    is_dir_sep(c) || c == '\0')

^ permalink raw reply related

* Re: Re* How to generate pull-request with info of signed tag
From: Junio C Hamano @ 2011-12-21 18:39 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: Git Mailing List
In-Reply-To: <87ipl9yik6.fsf@linux.vnet.ibm.com>

"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> writes:

> With an entry like below
>
> [remote "github"]
>         fetch = +refs/tags/*:refs/tags/origin/*
>         url = git://github.com/kvaneesh/QEMU.git
>
> when i do git fetch github for-anthony i get the below error

When you give refspecs from the command line like that, the default
refspec remote.github.fetch will not be used and what you configure there
is immaterial.

> [master@QEMU]$ git fetch github for-anthony
>>From git://github.com/kvaneesh/QEMU
>  * tag               for-anthony -> FETCH_HEAD

Sounds sane.

Does "git cat-file -t FETCH_HEAD" report "tag" (it should)?  After doing
that fetch and inspecting "git log -p ..FETCH_HEAD", you should be able to
do "git merge FETCH_HEAD" and it should be like you did "git pull github
for-anthony".

> Also trying to do
>
> [master@QEMU]$ git fetch git://github.com/kvaneesh/QEMU.git  for-anthony:aneesh/for-anthony
> error: Trying to write non-commit object 12916047784615b7d8b879d9d39be6c1559e1b1b to branch refs/heads/aneesh/for-anthony
>>From git://github.com/kvaneesh/QEMU
>  ! [new branch]      for-anthony -> aneesh/for-anthony  (unable to update local ref)
>  * [new tag]         for-anthony -> for-anthony

Sounds sane, too.

> I understand that replacing the above with below works. But we should
> not be required to specify refs/tags there right ?
>
> [master@QEMU]$ git fetch git://github.com/kvaneesh/QEMU.git  refs/tags/for-anthony:refs/tags/aneesh/for-anthony

If the "for-anthony" name is ambiguous between branches and tags, then you
must disambiguate. I am guessing that the unqualified LHS "for-anthony" is
found in the branch namespace of the remote, and that is why RHS is qualified
with the same refs/heads/ prefix to store it to the branch namespace.

On the other hand, if "for-anthony" name is unambiguous, then you may have
found a bug. I cannot tell.

^ permalink raw reply

* Re: Patches for message-digest support
From: Bill Zaumen @ 2011-12-21 18:44 UTC (permalink / raw)
  To: git, peff, pclouds

... sorry for an additional message.  The patches I just sent
were based on commit 876a6f4991abdd72ea707b193b4f2b831096ad3c
(Update draft release notes to 1.7.9).

I should have also added that the function verify_commit was
tested via a compile-time option, but it is currently not used.
Its purpose is to verify that the (new) digest header in commit
messages is consistent with the commit's tree, parents, other
headers, and the commit message.   For authentication, one
would want to sign the commit SHA-1 hash and the message digest
for the commit (which is stored separate from the commit object).
My patch doesn't do that, but there is a single function that
can be called to look up the digest, if one is present (which may
not be the case due to backwards compatibility issues) - I'd prefer
to have someone familiar with the signature code make any changes.

The version of Makefile in the patch turns off the commit message-digest
header because some of the test scripts won't run with it, due to
those encoding specific SHA-1 values and file lengths, but the test does
run far enough to have created and used a number of commits.  I didn't
want to go to the trouble of updating the test scripts unless the patch
is actually going to get used - updating the scripts is a bit tedious
and you'd probably want to decide on the digest hash first.

Bill

^ permalink raw reply

* Re: [PATCH] bash completion: use read -r everywhere
From: Junio C Hamano @ 2011-12-21 18:59 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git, Kevin Ballard
In-Reply-To: <4502a0248bb843018335e9b5cdf70736c096ebe3.1324482693.git.trast@student.ethz.ch>

Thomas Rast <trast@student.ethz.ch> writes:

> POSIX specifies
>
>   The read utility shall read a single line from standard input.
>   By default, unless the -r option is specified, backslash ('\')
>   shall act as an escape character...
>
> Our omission of -r breaks the loop reading refnames from
> git-for-each-ref in __git_refs() if there are refnames such as
> "foo'bar", in which case for-each-ref helpfully quotes them as in
>
>   $ git update-ref "refs/remotes/test/foo'bar" HEAD
>   $ git for-each-ref --shell --format="ref=%(refname:short)" "refs/remotes"
>   ref='test/foo'\''bar'
>
> Interpolating the \' here will read "ref='test/foo'''bar'" instead,
> and eval then chokes on the unbalanced quotes.
>
> However, since none of the read loops _want_ to have backslashes
> interpolated, it's much safer to use read -r everywhere.
>
> Signed-off-by: Thomas Rast <trast@student.ethz.ch>

Thanks.

As this script is specific to bash, it is secondary importance what POSIX
says. The "-r" option is important only because "bash" happens to follow
POSIX in this case. I'd like to see the early part of the message reworded
perhaps like this:

	At various points in the script, we use "read" utility without
	giving it the "-r" option that prevents a backslash ('\')
	character to act as an escape character. This breaks e.g. reading
	refnames from ...

Does this regress for zsh users in some ways, by the way?

> ---
>  contrib/completion/git-completion.bash |   12 ++++++------
>  1 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 78257ae..e7a39ef 100755
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -111,7 +111,7 @@ __git_ps1_show_upstream ()
>  
>  	# get some config options from git-config
>  	local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
> -	while read key value; do
> +	while read -r key value; do
>  		case "$key" in
>  		bash.showupstream)
>  			GIT_PS1_SHOWUPSTREAM="$value"
> @@ -589,7 +589,7 @@ __git_refs ()
>  			local ref entry
>  			git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \
>  				"refs/remotes/" | \
> -			while read entry; do
> +			while read -r entry; do
>  				eval "$entry"
>  				ref="${ref#*/}"
>  				if [[ "$ref" == "$cur"* ]]; then
> @@ -602,7 +602,7 @@ __git_refs ()
>  	case "$cur" in
>  	refs|refs/*)
>  		git ls-remote "$dir" "$cur*" 2>/dev/null | \
> -		while read hash i; do
> +		while read -r hash i; do
>  			case "$i" in
>  			*^{}) ;;
>  			*) echo "$i" ;;
> @@ -611,7 +611,7 @@ __git_refs ()
>  		;;
>  	*)
>  		git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \
> -		while read hash i; do
> +		while read -r hash i; do
>  			case "$i" in
>  			*^{}) ;;
>  			refs/*) echo "${i#refs/*/}" ;;
> @@ -636,7 +636,7 @@ __git_refs_remotes ()
>  {
>  	local i hash
>  	git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \
> -	while read hash i; do
> +	while read -r hash i; do
>  		echo "$i:refs/remotes/$1/${i#refs/heads/}"
>  	done
>  }
> @@ -1863,7 +1863,7 @@ __git_config_get_set_variables ()
>  	done
>  
>  	git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
> -	while read line
> +	while read -r line
>  	do
>  		case "$line" in
>  		*.*=*)

^ permalink raw reply

* Re: [PATCH 4/4] Suppress "statement not reached" warnings under Sun Studio
From: Ævar Arnfjörð Bjarmason @ 2011-12-21 19:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Elijah Newren, Jason Evans, David Barr
In-Reply-To: <7vvcp9hjam.fsf@alter.siamese.dyndns.org>

On Wed, Dec 21, 2011 at 19:27, Junio C Hamano <gitster@pobox.com> wrote:
> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> diff --git a/read-cache.c b/read-cache.c
>> index a51bba1..0a4e895 100644
>> --- a/read-cache.c
>> +++ b/read-cache.c
>> @@ -758,7 +758,13 @@ int verify_path(const char *path)
>>               return 0;
>>
>>       goto inside;
>> +#ifdef __sun
>> +#    pragma error_messages (off, E_STATEMENT_NOT_REACHED)
>> +#endif
>>       for (;;) {
>> +#ifdef __sun
>> +#    pragma error_messages (on, E_STATEMENT_NOT_REACHED)
>> +#endif
>>               if (!c)
>>                       return 1;
>
> Patches 1-3 makes sense, but this one is too ugly to live.
>
> Wouldn't something like this be equivalent and have the same effect
> without sacrificing the readablity?
>
> diff --git a/read-cache.c b/read-cache.c
> index a51bba1..73af797 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -757,12 +757,12 @@ int verify_path(const char *path)
>        if (has_dos_drive_prefix(path))
>                return 0;
>
> -       goto inside;
> +       /* we are at the beginning of a path component */
> +       c = '/';
>        for (;;) {
>                if (!c)
>                        return 1;
>                if (is_dir_sep(c)) {
> -inside:
>                        c = *path++;
>                        if ((c == '.' && !verify_dotfile(path)) ||
>                            is_dir_sep(c) || c == '\0')

That would make that warning go away, but I don't know if that changes
the semantics of the code. I was aiming not to change any code, just
to squash spurious warnings under Sun Studio.

We could also just wrap the whole function definition in the pragma,
which would make the code more readable since we wouldn't have 6 lines
of warning suppression in the middle of the function.

Or we could just drop this patch entirely, or rewrite the code. Your
pick.

^ permalink raw reply


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