Git development
 help / color / mirror / Atom feed
* [PATCH v2 07/20] builtin: convert textconv_object to use struct object_id
From: brian m. carlson @ 2016-09-05 20:07 UTC (permalink / raw)
  To: git
  Cc: Paul Tan, Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Jeff King, Johannes Schindelin, Jakub Narębski
In-Reply-To: <20160905200811.697889-1-sandals@crustytoothpaste.net>

Since all of its callers have been updated, make textconv_object take a
struct object_id.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 builtin.h          |  2 +-
 builtin/blame.c    | 12 ++++++------
 builtin/cat-file.c |  2 +-
 builtin/log.c      |  2 +-
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/builtin.h b/builtin.h
index 6b95006a..b9122bc5 100644
--- a/builtin.h
+++ b/builtin.h
@@ -25,7 +25,7 @@ struct fmt_merge_msg_opts {
 extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 			 struct fmt_merge_msg_opts *);
 
-extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);
+extern int textconv_object(const char *path, unsigned mode, const struct object_id *oid, int oid_valid, char **buf, unsigned long *buf_size);
 
 extern int is_builtin(const char *s);
 
diff --git a/builtin/blame.c b/builtin/blame.c
index 9c09d464..0e10e302 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -154,8 +154,8 @@ static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b,
  */
 int textconv_object(const char *path,
 		    unsigned mode,
-		    const unsigned char *sha1,
-		    int sha1_valid,
+		    const struct object_id *oid,
+		    int oid_valid,
 		    char **buf,
 		    unsigned long *buf_size)
 {
@@ -163,7 +163,7 @@ int textconv_object(const char *path,
 	struct userdiff_driver *textconv;
 
 	df = alloc_filespec(path);
-	fill_filespec(df, sha1, sha1_valid, mode);
+	fill_filespec(df, oid->hash, oid_valid, mode);
 	textconv = get_textconv(df);
 	if (!textconv) {
 		free_filespec(df);
@@ -188,7 +188,7 @@ static void fill_origin_blob(struct diff_options *opt,
 
 		num_read_blob++;
 		if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
-		    textconv_object(o->path, o->mode, o->blob_oid.hash, 1, &file->ptr, &file_size))
+		    textconv_object(o->path, o->mode, &o->blob_oid, 1, &file->ptr, &file_size))
 			;
 		else
 			file->ptr = read_sha1_file(o->blob_oid.hash, &type,
@@ -2366,7 +2366,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
 		switch (st.st_mode & S_IFMT) {
 		case S_IFREG:
 			if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
-			    textconv_object(read_from, mode, null_sha1, 0, &buf_ptr, &buf_len))
+			    textconv_object(read_from, mode, &null_oid, 0, &buf_ptr, &buf_len))
 				strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);
 			else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
 				die_errno("cannot open or read '%s'", read_from);
@@ -2793,7 +2793,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 			die("no such path %s in %s", path, final_commit_name);
 
 		if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) &&
-		    textconv_object(path, o->mode, o->blob_oid.hash, 1, (char **) &sb.final_buf,
+		    textconv_object(path, o->mode, &o->blob_oid, 1, (char **) &sb.final_buf,
 				    &sb.final_buf_size))
 			;
 		else
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 8b773787..7b2e0537 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -66,7 +66,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 			die("git cat-file --textconv %s: <object> must be <sha1:path>",
 			    obj_name);
 
-		if (textconv_object(obj_context.path, obj_context.mode, oid.hash, 1, &buf, &size))
+		if (textconv_object(obj_context.path, obj_context.mode, &oid, 1, &buf, &size))
 			break;
 
 	case 'p':
diff --git a/builtin/log.c b/builtin/log.c
index 226212c9..48b9db51 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -479,7 +479,7 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
 	if (get_sha1_with_context(obj_name, 0, oidc.hash, &obj_context))
 		die(_("Not a valid object name %s"), obj_name);
 	if (!obj_context.path[0] ||
-	    !textconv_object(obj_context.path, obj_context.mode, oidc.hash, 1, &buf, &size))
+	    !textconv_object(obj_context.path, obj_context.mode, &oidc, 1, &buf, &size))
 		return stream_blob_to_fd(1, oid->hash, NULL, 0);
 
 	if (!buf)

^ permalink raw reply related

* [PATCH v2 05/20] builtin/cat-file: convert struct expand_data to use struct object_id
From: brian m. carlson @ 2016-09-05 20:07 UTC (permalink / raw)
  To: git
  Cc: Paul Tan, Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Jeff King, Johannes Schindelin, Jakub Narębski
In-Reply-To: <20160905200811.697889-1-sandals@crustytoothpaste.net>

Convert struct cache_entry to use struct object_id by applying the
following semantic patch and the object_id transforms from contrib,
plus the actual change to the struct:

@@
struct expand_data E1;
@@
- E1.sha1
+ E1.oid.hash

@@
struct expand_data *E1;
@@
- E1->sha1
+ E1->oid.hash

@@
struct expand_data E1;
@@
- E1.delta_base_sha1
+ E1.delta_base_oid.hash

@@
struct expand_data *E1;
@@
- E1->delta_base_sha1
+ E1->delta_base_oid.hash

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 builtin/cat-file.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 2dfe6265..16b0b8c9 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -128,12 +128,12 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 }
 
 struct expand_data {
-	unsigned char sha1[20];
+	struct object_id oid;
 	enum object_type type;
 	unsigned long size;
 	off_t disk_size;
 	const char *rest;
-	unsigned char delta_base_sha1[20];
+	struct object_id delta_base_oid;
 
 	/*
 	 * If mark_query is true, we do not expand anything, but rather
@@ -176,7 +176,7 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,
 
 	if (is_atom("objectname", atom, len)) {
 		if (!data->mark_query)
-			strbuf_addstr(sb, sha1_to_hex(data->sha1));
+			strbuf_addstr(sb, oid_to_hex(&data->oid));
 	} else if (is_atom("objecttype", atom, len)) {
 		if (data->mark_query)
 			data->info.typep = &data->type;
@@ -199,9 +199,10 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,
 			strbuf_addstr(sb, data->rest);
 	} else if (is_atom("deltabase", atom, len)) {
 		if (data->mark_query)
-			data->info.delta_base_sha1 = data->delta_base_sha1;
+			data->info.delta_base_sha1 = data->delta_base_oid.hash;
 		else
-			strbuf_addstr(sb, sha1_to_hex(data->delta_base_sha1));
+			strbuf_addstr(sb,
+				      oid_to_hex(&data->delta_base_oid));
 	} else
 		die("unknown format element: %.*s", len, atom);
 }
@@ -232,7 +233,7 @@ static void batch_write(struct batch_options *opt, const void *data, int len)
 
 static void print_object_or_die(struct batch_options *opt, struct expand_data *data)
 {
-	const unsigned char *sha1 = data->sha1;
+	const unsigned char *sha1 = data->oid.hash;
 
 	assert(data->info.typep);
 
@@ -266,8 +267,9 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,
 	struct strbuf buf = STRBUF_INIT;
 
 	if (!data->skip_object_info &&
-	    sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) {
-		printf("%s missing\n", obj_name ? obj_name : sha1_to_hex(data->sha1));
+	    sha1_object_info_extended(data->oid.hash, &data->info, LOOKUP_REPLACE_OBJECT) < 0) {
+		printf("%s missing\n",
+		       obj_name ? obj_name : oid_to_hex(&data->oid));
 		fflush(stdout);
 		return;
 	}
@@ -290,7 +292,7 @@ static void batch_one_object(const char *obj_name, struct batch_options *opt,
 	int flags = opt->follow_symlinks ? GET_SHA1_FOLLOW_SYMLINKS : 0;
 	enum follow_symlinks_result result;
 
-	result = get_sha1_with_context(obj_name, flags, data->sha1, &ctx);
+	result = get_sha1_with_context(obj_name, flags, data->oid.hash, &ctx);
 	if (result != FOUND) {
 		switch (result) {
 		case MISSING_OBJECT:
@@ -336,7 +338,7 @@ struct object_cb_data {
 static void batch_object_cb(const unsigned char sha1[20], void *vdata)
 {
 	struct object_cb_data *data = vdata;
-	hashcpy(data->expand->sha1, sha1);
+	hashcpy(data->expand->oid.hash, sha1);
 	batch_object_write(NULL, data->opt, data->expand);
 }
 

^ permalink raw reply related

* [PATCH v2 06/20] builtin/cat-file: convert some static functions to struct object_id
From: brian m. carlson @ 2016-09-05 20:07 UTC (permalink / raw)
  To: git
  Cc: Paul Tan, Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Jeff King, Johannes Schindelin, Jakub Narębski
In-Reply-To: <20160905200811.697889-1-sandals@crustytoothpaste.net>

Convert all of the static functions that are not callbacks to use struct
object_id.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 builtin/cat-file.c | 50 +++++++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 16b0b8c9..8b773787 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -23,7 +23,7 @@ struct batch_options {
 static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 			int unknown_type)
 {
-	unsigned char sha1[20];
+	struct object_id oid;
 	enum object_type type;
 	char *buf;
 	unsigned long size;
@@ -35,14 +35,14 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 	if (unknown_type)
 		flags |= LOOKUP_UNKNOWN_OBJECT;
 
-	if (get_sha1_with_context(obj_name, 0, sha1, &obj_context))
+	if (get_sha1_with_context(obj_name, 0, oid.hash, &obj_context))
 		die("Not a valid object name %s", obj_name);
 
 	buf = NULL;
 	switch (opt) {
 	case 't':
 		oi.typename = &sb;
-		if (sha1_object_info_extended(sha1, &oi, flags) < 0)
+		if (sha1_object_info_extended(oid.hash, &oi, flags) < 0)
 			die("git cat-file: could not get object info");
 		if (sb.len) {
 			printf("%s\n", sb.buf);
@@ -53,24 +53,24 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 
 	case 's':
 		oi.sizep = &size;
-		if (sha1_object_info_extended(sha1, &oi, flags) < 0)
+		if (sha1_object_info_extended(oid.hash, &oi, flags) < 0)
 			die("git cat-file: could not get object info");
 		printf("%lu\n", size);
 		return 0;
 
 	case 'e':
-		return !has_sha1_file(sha1);
+		return !has_object_file(&oid);
 
 	case 'c':
 		if (!obj_context.path[0])
 			die("git cat-file --textconv %s: <object> must be <sha1:path>",
 			    obj_name);
 
-		if (textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size))
+		if (textconv_object(obj_context.path, obj_context.mode, oid.hash, 1, &buf, &size))
 			break;
 
 	case 'p':
-		type = sha1_object_info(sha1, NULL);
+		type = sha1_object_info(oid.hash, NULL);
 		if (type < 0)
 			die("Not a valid object name %s", obj_name);
 
@@ -83,8 +83,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 		}
 
 		if (type == OBJ_BLOB)
-			return stream_blob_to_fd(1, sha1, NULL, 0);
-		buf = read_sha1_file(sha1, &type, &size);
+			return stream_blob_to_fd(1, oid.hash, NULL, 0);
+		buf = read_sha1_file(oid.hash, &type, &size);
 		if (!buf)
 			die("Cannot read object %s", obj_name);
 
@@ -93,19 +93,19 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 
 	case 0:
 		if (type_from_string(exp_type) == OBJ_BLOB) {
-			unsigned char blob_sha1[20];
-			if (sha1_object_info(sha1, NULL) == OBJ_TAG) {
-				char *buffer = read_sha1_file(sha1, &type, &size);
+			struct object_id blob_oid;
+			if (sha1_object_info(oid.hash, NULL) == OBJ_TAG) {
+				char *buffer = read_sha1_file(oid.hash, &type, &size);
 				const char *target;
 				if (!skip_prefix(buffer, "object ", &target) ||
-				    get_sha1_hex(target, blob_sha1))
-					die("%s not a valid tag", sha1_to_hex(sha1));
+				    get_oid_hex(target, &blob_oid))
+					die("%s not a valid tag", oid_to_hex(&oid));
 				free(buffer);
 			} else
-				hashcpy(blob_sha1, sha1);
+				oidcpy(&blob_oid, &oid);
 
-			if (sha1_object_info(blob_sha1, NULL) == OBJ_BLOB)
-				return stream_blob_to_fd(1, blob_sha1, NULL, 0);
+			if (sha1_object_info(blob_oid.hash, NULL) == OBJ_BLOB)
+				return stream_blob_to_fd(1, blob_oid.hash, NULL, 0);
 			/*
 			 * we attempted to dereference a tag to a blob
 			 * and failed; there may be new dereference
@@ -113,7 +113,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 			 * fall-back to the usual case.
 			 */
 		}
-		buf = read_object_with_reference(sha1, exp_type, &size, NULL);
+		buf = read_object_with_reference(oid.hash, exp_type, &size, NULL);
 		break;
 
 	default:
@@ -233,28 +233,28 @@ static void batch_write(struct batch_options *opt, const void *data, int len)
 
 static void print_object_or_die(struct batch_options *opt, struct expand_data *data)
 {
-	const unsigned char *sha1 = data->oid.hash;
+	const struct object_id *oid = &data->oid;
 
 	assert(data->info.typep);
 
 	if (data->type == OBJ_BLOB) {
 		if (opt->buffer_output)
 			fflush(stdout);
-		if (stream_blob_to_fd(1, sha1, NULL, 0) < 0)
-			die("unable to stream %s to stdout", sha1_to_hex(sha1));
+		if (stream_blob_to_fd(1, oid->hash, NULL, 0) < 0)
+			die("unable to stream %s to stdout", oid_to_hex(oid));
 	}
 	else {
 		enum object_type type;
 		unsigned long size;
 		void *contents;
 
-		contents = read_sha1_file(sha1, &type, &size);
+		contents = read_sha1_file(oid->hash, &type, &size);
 		if (!contents)
-			die("object %s disappeared", sha1_to_hex(sha1));
+			die("object %s disappeared", oid_to_hex(oid));
 		if (type != data->type)
-			die("object %s changed type!?", sha1_to_hex(sha1));
+			die("object %s changed type!?", oid_to_hex(oid));
 		if (data->info.sizep && size != data->size)
-			die("object %s changed size!?", sha1_to_hex(sha1));
+			die("object %s changed size!?", oid_to_hex(oid));
 
 		batch_write(opt, contents, size);
 		free(contents);

^ permalink raw reply related

* [PATCH v2 04/20] builtin/log: convert some static functions to use struct object_id
From: brian m. carlson @ 2016-09-05 20:07 UTC (permalink / raw)
  To: git
  Cc: Paul Tan, Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Jeff King, Johannes Schindelin, Jakub Narębski
In-Reply-To: <20160905200811.697889-1-sandals@crustytoothpaste.net>

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 builtin/log.c | 44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/builtin/log.c b/builtin/log.c
index 92dc34dc..226212c9 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -464,9 +464,9 @@ static void show_tagger(char *buf, int len, struct rev_info *rev)
 	strbuf_release(&out);
 }
 
-static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, const char *obj_name)
+static int show_blob_object(const struct object_id *oid, struct rev_info *rev, const char *obj_name)
 {
-	unsigned char sha1c[20];
+	struct object_id oidc;
 	struct object_context obj_context;
 	char *buf;
 	unsigned long size;
@@ -474,13 +474,13 @@ static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, con
 	fflush(rev->diffopt.file);
 	if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) ||
 	    !DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
-		return stream_blob_to_fd(1, sha1, NULL, 0);
+		return stream_blob_to_fd(1, oid->hash, NULL, 0);
 
-	if (get_sha1_with_context(obj_name, 0, sha1c, &obj_context))
+	if (get_sha1_with_context(obj_name, 0, oidc.hash, &obj_context))
 		die(_("Not a valid object name %s"), obj_name);
 	if (!obj_context.path[0] ||
-	    !textconv_object(obj_context.path, obj_context.mode, sha1c, 1, &buf, &size))
-		return stream_blob_to_fd(1, sha1, NULL, 0);
+	    !textconv_object(obj_context.path, obj_context.mode, oidc.hash, 1, &buf, &size))
+		return stream_blob_to_fd(1, oid->hash, NULL, 0);
 
 	if (!buf)
 		die(_("git show %s: bad file"), obj_name);
@@ -489,15 +489,15 @@ static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, con
 	return 0;
 }
 
-static int show_tag_object(const unsigned char *sha1, struct rev_info *rev)
+static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
 {
 	unsigned long size;
 	enum object_type type;
-	char *buf = read_sha1_file(sha1, &type, &size);
+	char *buf = read_sha1_file(oid->hash, &type, &size);
 	int offset = 0;
 
 	if (!buf)
-		return error(_("Could not read object %s"), sha1_to_hex(sha1));
+		return error(_("Could not read object %s"), oid_to_hex(oid));
 
 	assert(type == OBJ_TAG);
 	while (offset < size && buf[offset] != '\n') {
@@ -574,7 +574,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 		const char *name = objects[i].name;
 		switch (o->type) {
 		case OBJ_BLOB:
-			ret = show_blob_object(o->oid.hash, &rev, name);
+			ret = show_blob_object(&o->oid, &rev, name);
 			break;
 		case OBJ_TAG: {
 			struct tag *t = (struct tag *)o;
@@ -585,7 +585,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 					diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
 					t->tag,
 					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
-			ret = show_tag_object(o->oid.hash, &rev);
+			ret = show_tag_object(&o->oid, &rev);
 			rev.shown_one = 1;
 			if (ret)
 				break;
@@ -1248,11 +1248,11 @@ static struct commit *get_base_commit(const char *base_commit,
 		if (upstream) {
 			struct commit_list *base_list;
 			struct commit *commit;
-			unsigned char sha1[20];
+			struct object_id oid;
 
-			if (get_sha1(upstream, sha1))
+			if (get_oid(upstream, &oid))
 				die(_("Failed to resolve '%s' as a valid ref."), upstream);
-			commit = lookup_commit_or_die(sha1, "upstream base");
+			commit = lookup_commit_or_die(oid.hash, "upstream base");
 			base_list = get_merge_bases_many(commit, total, list);
 			/* There should be one and only one merge base. */
 			if (!base_list || base_list->next)
@@ -1339,15 +1339,15 @@ static void prepare_bases(struct base_tree_info *bases,
 	 * and stuff them in bases structure.
 	 */
 	while ((commit = get_revision(&revs)) != NULL) {
-		unsigned char sha1[20];
+		struct object_id oid;
 		struct object_id *patch_id;
 		if (commit->util)
 			continue;
-		if (commit_patch_id(commit, &diffopt, sha1, 0))
+		if (commit_patch_id(commit, &diffopt, oid.hash, 0))
 			die(_("cannot get patch id"));
 		ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
 		patch_id = bases->patch_id + bases->nr_patch_id;
-		hashcpy(patch_id->hash, sha1);
+		oidcpy(patch_id, &oid);
 		bases->nr_patch_id++;
 	}
 }
@@ -1628,10 +1628,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 			check_head = 1;
 
 		if (check_head) {
-			unsigned char sha1[20];
+			struct object_id oid;
 			const char *ref, *v;
 			ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
-						 sha1, NULL);
+						 oid.hash, NULL);
 			if (ref && skip_prefix(ref, "refs/heads/", &v))
 				branch_name = xstrdup(v);
 			else
@@ -1802,9 +1802,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 
 static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
 {
-	unsigned char sha1[20];
-	if (get_sha1(arg, sha1) == 0) {
-		struct commit *commit = lookup_commit_reference(sha1);
+	struct object_id oid;
+	if (get_oid(arg, &oid) == 0) {
+		struct commit *commit = lookup_commit_reference(oid.hash);
 		if (commit) {
 			commit->object.flags |= flags;
 			add_pending_object(revs, &commit->object, arg);

^ permalink raw reply related

* [PATCH v2 03/20] builtin/blame: convert struct origin to use struct object_id
From: brian m. carlson @ 2016-09-05 20:07 UTC (permalink / raw)
  To: git
  Cc: Paul Tan, Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Jeff King, Johannes Schindelin, Jakub Narębski
In-Reply-To: <20160905200811.697889-1-sandals@crustytoothpaste.net>

Convert struct origin to use struct object_id by applying the
following semantic patch and the object_id transforms from contrib,
plus the actual change to the struct:

@@
struct origin E1;
@@
- E1.blob_sha1
+ E1.blob_oid.hash

@@
struct origin *E1;
@@
- E1->blob_sha1
+ E1->blob_oid.hash

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 builtin/blame.c | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index 5eb3725d..9c09d464 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -120,7 +120,7 @@ struct origin {
 	 */
 	struct blame_entry *suspects;
 	mmfile_t file;
-	unsigned char blob_sha1[20];
+	struct object_id blob_oid;
 	unsigned mode;
 	/* guilty gets set when shipping any suspects to the final
 	 * blame list instead of other commits
@@ -188,15 +188,16 @@ static void fill_origin_blob(struct diff_options *opt,
 
 		num_read_blob++;
 		if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
-		    textconv_object(o->path, o->mode, o->blob_sha1, 1, &file->ptr, &file_size))
+		    textconv_object(o->path, o->mode, o->blob_oid.hash, 1, &file->ptr, &file_size))
 			;
 		else
-			file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size);
+			file->ptr = read_sha1_file(o->blob_oid.hash, &type,
+						   &file_size);
 		file->size = file_size;
 
 		if (!file->ptr)
 			die("Cannot read blob %s for path %s",
-			    sha1_to_hex(o->blob_sha1),
+			    oid_to_hex(&o->blob_oid),
 			    o->path);
 		o->file = *file;
 	}
@@ -508,17 +509,17 @@ static struct origin *get_origin(struct scoreboard *sb,
  */
 static int fill_blob_sha1_and_mode(struct origin *origin)
 {
-	if (!is_null_sha1(origin->blob_sha1))
+	if (!is_null_oid(&origin->blob_oid))
 		return 0;
 	if (get_tree_entry(origin->commit->object.oid.hash,
 			   origin->path,
-			   origin->blob_sha1, &origin->mode))
+			   origin->blob_oid.hash, &origin->mode))
 		goto error_out;
-	if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB)
+	if (sha1_object_info(origin->blob_oid.hash, NULL) != OBJ_BLOB)
 		goto error_out;
 	return 0;
  error_out:
-	hashclr(origin->blob_sha1);
+	oidclr(&origin->blob_oid);
 	origin->mode = S_IFINVALID;
 	return -1;
 }
@@ -572,7 +573,7 @@ static struct origin *find_origin(struct scoreboard *sb,
 	if (!diff_queued_diff.nr) {
 		/* The path is the same as parent */
 		porigin = get_origin(sb, parent, origin->path);
-		hashcpy(porigin->blob_sha1, origin->blob_sha1);
+		oidcpy(&porigin->blob_oid, &origin->blob_oid);
 		porigin->mode = origin->mode;
 	} else {
 		/*
@@ -598,7 +599,7 @@ static struct origin *find_origin(struct scoreboard *sb,
 			    p->status);
 		case 'M':
 			porigin = get_origin(sb, parent, origin->path);
-			hashcpy(porigin->blob_sha1, p->one->oid.hash);
+			oidcpy(&porigin->blob_oid, &p->one->oid);
 			porigin->mode = p->one->mode;
 			break;
 		case 'A':
@@ -644,7 +645,7 @@ static struct origin *find_rename(struct scoreboard *sb,
 		if ((p->status == 'R' || p->status == 'C') &&
 		    !strcmp(p->two->path, origin->path)) {
 			porigin = get_origin(sb, parent, p->one->path);
-			hashcpy(porigin->blob_sha1, p->one->oid.hash);
+			oidcpy(&porigin->blob_oid, &p->one->oid);
 			porigin->mode = p->one->mode;
 			break;
 		}
@@ -1308,7 +1309,7 @@ static void find_copy_in_parent(struct scoreboard *sb,
 				continue;
 
 			norigin = get_origin(sb, parent, p->one->path);
-			hashcpy(norigin->blob_sha1, p->one->oid.hash);
+			oidcpy(&norigin->blob_oid, &p->one->oid);
 			norigin->mode = p->one->mode;
 			fill_origin_blob(&sb->revs->diffopt, norigin, &file_p);
 			if (!file_p.ptr)
@@ -1458,15 +1459,14 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 			porigin = find(sb, p, origin);
 			if (!porigin)
 				continue;
-			if (!hashcmp(porigin->blob_sha1, origin->blob_sha1)) {
+			if (!oidcmp(&porigin->blob_oid, &origin->blob_oid)) {
 				pass_whole_blame(sb, origin, porigin);
 				origin_decref(porigin);
 				goto finish;
 			}
 			for (j = same = 0; j < i; j++)
 				if (sg_origin[j] &&
-				    !hashcmp(sg_origin[j]->blob_sha1,
-					     porigin->blob_sha1)) {
+				    !oidcmp(&sg_origin[j]->blob_oid, &porigin->blob_oid)) {
 					same = 1;
 					break;
 				}
@@ -2388,7 +2388,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
 	convert_to_git(path, buf.buf, buf.len, &buf, 0);
 	origin->file.ptr = buf.buf;
 	origin->file.size = buf.len;
-	pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1);
+	pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_oid.hash);
 
 	/*
 	 * Read the current index, replace the path entry with
@@ -2410,7 +2410,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
 	}
 	size = cache_entry_size(len);
 	ce = xcalloc(1, size);
-	hashcpy(ce->oid.hash, origin->blob_sha1);
+	oidcpy(&ce->oid, &origin->blob_oid);
 	memcpy(ce->name, path, len);
 	ce->ce_flags = create_ce_flags(0);
 	ce->ce_namelen = len;
@@ -2793,16 +2793,16 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 			die("no such path %s in %s", path, final_commit_name);
 
 		if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) &&
-		    textconv_object(path, o->mode, o->blob_sha1, 1, (char **) &sb.final_buf,
+		    textconv_object(path, o->mode, o->blob_oid.hash, 1, (char **) &sb.final_buf,
 				    &sb.final_buf_size))
 			;
 		else
-			sb.final_buf = read_sha1_file(o->blob_sha1, &type,
+			sb.final_buf = read_sha1_file(o->blob_oid.hash, &type,
 						      &sb.final_buf_size);
 
 		if (!sb.final_buf)
 			die("Cannot read blob %s for path %s",
-			    sha1_to_hex(o->blob_sha1),
+			    oid_to_hex(&o->blob_oid),
 			    path);
 	}
 	num_read_blob++;

^ permalink raw reply related

* [PATCH v2 01/20] cache: convert struct cache_entry to use struct object_id
From: brian m. carlson @ 2016-09-05 20:07 UTC (permalink / raw)
  To: git
  Cc: Paul Tan, Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Jeff King, Johannes Schindelin, Jakub Narębski
In-Reply-To: <20160905200811.697889-1-sandals@crustytoothpaste.net>

Convert struct cache_entry to use struct object_id by applying the
following semantic patch and the object_id transforms from contrib, plus
the actual change to the struct:

@@
struct cache_entry E1;
@@
- E1.sha1
+ E1.oid.hash

@@
struct cache_entry *E1;
@@
- E1->sha1
+ E1->oid.hash

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 builtin/apply.c                  | 10 +++++-----
 builtin/blame.c                  |  2 +-
 builtin/checkout.c               |  6 +++---
 builtin/fsck.c                   |  2 +-
 builtin/grep.c                   |  3 ++-
 builtin/ls-files.c               |  2 +-
 builtin/merge-index.c            |  2 +-
 builtin/read-tree.c              |  2 +-
 builtin/rm.c                     |  2 +-
 builtin/submodule--helper.c      |  5 +++--
 builtin/update-index.c           | 10 +++++-----
 cache-tree.c                     |  4 ++--
 cache.h                          |  2 +-
 diff-lib.c                       | 31 ++++++++++++++++++-------------
 diff.c                           |  2 +-
 dir.c                            |  7 ++++---
 entry.c                          |  9 +++++----
 merge-recursive.c                |  2 +-
 read-cache.c                     | 24 ++++++++++++------------
 rerere.c                         |  3 ++-
 resolve-undo.c                   |  2 +-
 revision.c                       |  2 +-
 sha1_name.c                      |  2 +-
 t/helper/test-dump-split-index.c |  2 +-
 tree.c                           |  2 +-
 unpack-trees.c                   |  8 ++++----
 26 files changed, 79 insertions(+), 69 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 1a488f9e..ba0e75bf 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3220,7 +3220,7 @@ static int read_file_or_gitlink(const struct cache_entry *ce, struct strbuf *buf
 {
 	if (!ce)
 		return 0;
-	return read_blob_object(buf, ce->sha1, ce->ce_mode);
+	return read_blob_object(buf, ce->oid.hash, ce->ce_mode);
 }
 
 static struct patch *in_fn_table(struct apply_state *state, const char *name)
@@ -3959,7 +3959,7 @@ static int get_current_sha1(const char *path, unsigned char *sha1)
 	pos = cache_name_pos(path, strlen(path));
 	if (pos < 0)
 		return -1;
-	hashcpy(sha1, active_cache[pos]->sha1);
+	hashcpy(sha1, active_cache[pos]->oid.hash);
 	return 0;
 }
 
@@ -4211,7 +4211,7 @@ static void add_index_file(struct apply_state *state,
 		const char *s;
 
 		if (!skip_prefix(buf, "Subproject commit ", &s) ||
-		    get_sha1_hex(s, ce->sha1))
+		    get_sha1_hex(s, ce->oid.hash))
 			die(_("corrupt patch for submodule %s"), path);
 	} else {
 		if (!state->cached) {
@@ -4220,7 +4220,7 @@ static void add_index_file(struct apply_state *state,
 					  path);
 			fill_stat_cache_info(ce, &st);
 		}
-		if (write_sha1_file(buf, size, blob_type, ce->sha1) < 0)
+		if (write_sha1_file(buf, size, blob_type, ce->oid.hash) < 0)
 			die(_("unable to create backing store for newly created file %s"), path);
 	}
 	if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0)
@@ -4335,7 +4335,7 @@ static void add_conflicted_stages_file(struct apply_state *state,
 		ce->ce_mode = create_ce_mode(mode);
 		ce->ce_flags = create_ce_flags(stage);
 		ce->ce_namelen = namelen;
-		hashcpy(ce->sha1, patch->threeway_stage[stage - 1].hash);
+		oidcpy(&ce->oid, &patch->threeway_stage[stage - 1]);
 		if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0)
 			die(_("unable to add cache entry for %s"), patch->new_name);
 	}
diff --git a/builtin/blame.c b/builtin/blame.c
index a5bbf91e..5eb3725d 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2410,7 +2410,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
 	}
 	size = cache_entry_size(len);
 	ce = xcalloc(1, size);
-	hashcpy(ce->sha1, origin->blob_sha1);
+	hashcpy(ce->oid.hash, origin->blob_sha1);
 	memcpy(ce->name, path, len);
 	ce->ce_flags = create_ce_flags(0);
 	ce->ce_namelen = len;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 8672d072..a9523ffa 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -76,7 +76,7 @@ static int update_some(const unsigned char *sha1, struct strbuf *base,
 
 	len = base->len + strlen(pathname);
 	ce = xcalloc(1, cache_entry_size(len));
-	hashcpy(ce->sha1, sha1);
+	hashcpy(ce->oid.hash, sha1);
 	memcpy(ce->name, base->buf, base->len);
 	memcpy(ce->name + base->len, pathname, len - base->len);
 	ce->ce_flags = create_ce_flags(0) | CE_UPDATE;
@@ -92,7 +92,7 @@ static int update_some(const unsigned char *sha1, struct strbuf *base,
 	if (pos >= 0) {
 		struct cache_entry *old = active_cache[pos];
 		if (ce->ce_mode == old->ce_mode &&
-		    !hashcmp(ce->sha1, old->sha1)) {
+		    !oidcmp(&ce->oid, &old->oid)) {
 			old->ce_flags |= CE_UPDATE;
 			free(ce);
 			return 0;
@@ -186,7 +186,7 @@ static int checkout_merged(int pos, struct checkout *state)
 		stage = ce_stage(ce);
 		if (!stage || strcmp(path, ce->name))
 			break;
-		hashcpy(threeway[stage - 1], ce->sha1);
+		hashcpy(threeway[stage - 1], ce->oid.hash);
 		if (stage == 2)
 			mode = create_ce_mode(ce->ce_mode);
 		pos++;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 2de272ea..f604adff 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -722,7 +722,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 			mode = active_cache[i]->ce_mode;
 			if (S_ISGITLINK(mode))
 				continue;
-			blob = lookup_blob(active_cache[i]->sha1);
+			blob = lookup_blob(active_cache[i]->oid.hash);
 			if (!blob)
 				continue;
 			obj = &blob->object;
diff --git a/builtin/grep.c b/builtin/grep.c
index ae738312..8887b6ad 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -398,7 +398,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
 		if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) {
 			if (ce_stage(ce) || ce_intent_to_add(ce))
 				continue;
-			hit |= grep_sha1(opt, ce->sha1, ce->name, 0, ce->name);
+			hit |= grep_sha1(opt, ce->oid.hash, ce->name, 0,
+					 ce->name);
 		}
 		else
 			hit |= grep_file(opt, ce->name);
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 00ea91aa..197f153f 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -187,7 +187,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 		printf("%s%06o %s %d\t",
 		       tag,
 		       ce->ce_mode,
-		       find_unique_abbrev(ce->sha1,abbrev),
+		       find_unique_abbrev(ce->oid.hash,abbrev),
 		       ce_stage(ce));
 	}
 	write_eolinfo(ce, ce->name);
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index 1c3427c3..ce356b1d 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -22,7 +22,7 @@ static int merge_entry(int pos, const char *path)
 		if (strcmp(ce->name, path))
 			break;
 		found++;
-		sha1_to_hex_r(hexbuf[stage], ce->sha1);
+		sha1_to_hex_r(hexbuf[stage], ce->oid.hash);
 		xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
 		arguments[stage] = hexbuf[stage];
 		arguments[stage + 4] = ownbuf[stage];
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 8c693e75..9bd1fd75 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -78,7 +78,7 @@ static void debug_stage(const char *label, const struct cache_entry *ce,
 	else
 		printf("%06o #%d %s %.8s\n",
 		       ce->ce_mode, ce_stage(ce), ce->name,
-		       sha1_to_hex(ce->sha1));
+		       oid_to_hex(&ce->oid));
 }
 
 static int debug_merge(const struct cache_entry * const *stages,
diff --git a/builtin/rm.c b/builtin/rm.c
index b2fee3e9..109969d5 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -199,7 +199,7 @@ static int check_local_mod(unsigned char *head, int index_only)
 		if (no_head
 		     || get_tree_entry(head, name, sha1, &mode)
 		     || ce->ce_mode != create_ce_mode(mode)
-		     || hashcmp(ce->sha1, sha1))
+		     || hashcmp(ce->oid.hash, sha1))
 			staged_changes = 1;
 
 		/*
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e79790f0..566cfdd7 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -296,7 +296,8 @@ static int module_list(int argc, const char **argv, const char *prefix)
 		if (ce_stage(ce))
 			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
 		else
-			printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce));
+			printf("%06o %s %d\t", ce->ce_mode,
+			       oid_to_hex(&ce->oid), ce_stage(ce));
 
 		utf8_fprintf(stdout, "%s\n", ce->name);
 	}
@@ -683,7 +684,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 
 	strbuf_reset(&sb);
 	strbuf_addf(&sb, "%06o %s %d %d\t%s\n", ce->ce_mode,
-			sha1_to_hex(ce->sha1), ce_stage(ce),
+			oid_to_hex(&ce->oid), ce_stage(ce),
 			needs_cloning, ce->name);
 	string_list_append(&suc->projectlines, sb.buf);
 
diff --git a/builtin/update-index.c b/builtin/update-index.c
index ba04b197..a60a30a8 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -275,7 +275,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
 	fill_stat_cache_info(ce, st);
 	ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
 
-	if (index_path(ce->sha1, path, st,
+	if (index_path(ce->oid.hash, path, st,
 		       info_only ? 0 : HASH_WRITE_OBJECT)) {
 		free(ce);
 		return -1;
@@ -403,7 +403,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
 	size = cache_entry_size(len);
 	ce = xcalloc(1, size);
 
-	hashcpy(ce->sha1, sha1);
+	hashcpy(ce->oid.hash, sha1);
 	memcpy(ce->name, path, len);
 	ce->ce_flags = create_ce_flags(stage);
 	ce->ce_namelen = len;
@@ -601,7 +601,7 @@ static struct cache_entry *read_one_ent(const char *which,
 	size = cache_entry_size(namelen);
 	ce = xcalloc(1, size);
 
-	hashcpy(ce->sha1, sha1);
+	hashcpy(ce->oid.hash, sha1);
 	memcpy(ce->name, path, namelen);
 	ce->ce_flags = create_ce_flags(stage);
 	ce->ce_namelen = namelen;
@@ -658,7 +658,7 @@ static int unresolve_one(const char *path)
 		ret = -1;
 		goto free_return;
 	}
-	if (!hashcmp(ce_2->sha1, ce_3->sha1) &&
+	if (!oidcmp(&ce_2->oid, &ce_3->oid) &&
 	    ce_2->ce_mode == ce_3->ce_mode) {
 		fprintf(stderr, "%s: identical in both, skipping.\n",
 			path);
@@ -743,7 +743,7 @@ static int do_reupdate(int ac, const char **av,
 			old = read_one_ent(NULL, head_sha1,
 					   ce->name, ce_namelen(ce), 0);
 		if (old && ce->ce_mode == old->ce_mode &&
-		    !hashcmp(ce->sha1, old->sha1)) {
+		    !oidcmp(&ce->oid, &old->oid)) {
 			free(old);
 			continue; /* unchanged */
 		}
diff --git a/cache-tree.c b/cache-tree.c
index f28b1f45..345ea359 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -168,7 +168,7 @@ static int verify_cache(struct cache_entry **cache,
 				break;
 			}
 			fprintf(stderr, "%s: unmerged (%s)\n",
-				ce->name, sha1_to_hex(ce->sha1));
+				ce->name, oid_to_hex(&ce->oid));
 		}
 	}
 	if (funny)
@@ -349,7 +349,7 @@ static int update_one(struct cache_tree *it,
 			}
 		}
 		else {
-			sha1 = ce->sha1;
+			sha1 = ce->oid.hash;
 			mode = ce->ce_mode;
 			entlen = pathlen - baselen;
 			i++;
diff --git a/cache.h b/cache.h
index b780a91a..a679484e 100644
--- a/cache.h
+++ b/cache.h
@@ -173,7 +173,7 @@ struct cache_entry {
 	unsigned int ce_flags;
 	unsigned int ce_namelen;
 	unsigned int index;	/* for link extension */
-	unsigned char sha1[20];
+	struct object_id oid;
 	char name[FLEX_ARRAY]; /* more */
 };
 
diff --git a/diff-lib.c b/diff-lib.c
index bc49c708..3007c852 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -155,7 +155,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 				if (2 <= stage) {
 					int mode = nce->ce_mode;
 					num_compare_stages++;
-					hashcpy(dpath->parent[stage-2].oid.hash, nce->sha1);
+					oidcpy(&dpath->parent[stage - 2].oid,
+					       &nce->oid);
 					dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode);
 					dpath->parent[stage-2].status =
 						DIFF_STATUS_MODIFIED;
@@ -209,7 +210,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 					continue;
 				}
 				diff_addremove(&revs->diffopt, '-', ce->ce_mode,
-					       ce->sha1, !is_null_sha1(ce->sha1),
+					       ce->oid.hash,
+					       !is_null_oid(&ce->oid),
 					       ce->name, 0);
 				continue;
 			}
@@ -225,8 +227,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 				continue;
 		}
 		oldmode = ce->ce_mode;
-		old_sha1 = ce->sha1;
-		new_sha1 = changed ? null_sha1 : ce->sha1;
+		old_sha1 = ce->oid.hash;
+		new_sha1 = changed ? null_sha1 : ce->oid.hash;
 		diff_change(&revs->diffopt, oldmode, newmode,
 			    old_sha1, new_sha1,
 			    !is_null_sha1(old_sha1),
@@ -261,7 +263,7 @@ static int get_stat_data(const struct cache_entry *ce,
 			 int cached, int match_missing,
 			 unsigned *dirty_submodule, struct diff_options *diffopt)
 {
-	const unsigned char *sha1 = ce->sha1;
+	const unsigned char *sha1 = ce->oid.hash;
 	unsigned int mode = ce->ce_mode;
 
 	if (!cached && !ce_uptodate(ce)) {
@@ -324,12 +326,13 @@ static int show_modified(struct rev_info *revs,
 			  &dirty_submodule, &revs->diffopt) < 0) {
 		if (report_missing)
 			diff_index_show_file(revs, "-", old,
-					     old->sha1, 1, old->ce_mode, 0);
+					     old->oid.hash, 1, old->ce_mode,
+					     0);
 		return -1;
 	}
 
 	if (revs->combine_merges && !cached &&
-	    (hashcmp(sha1, old->sha1) || hashcmp(old->sha1, new->sha1))) {
+	    (hashcmp(sha1, old->oid.hash) || oidcmp(&old->oid, &new->oid))) {
 		struct combine_diff_path *p;
 		int pathlen = ce_namelen(new);
 
@@ -343,22 +346,22 @@ static int show_modified(struct rev_info *revs,
 		memset(p->parent, 0, 2 * sizeof(struct combine_diff_parent));
 		p->parent[0].status = DIFF_STATUS_MODIFIED;
 		p->parent[0].mode = new->ce_mode;
-		hashcpy(p->parent[0].oid.hash, new->sha1);
+		oidcpy(&p->parent[0].oid, &new->oid);
 		p->parent[1].status = DIFF_STATUS_MODIFIED;
 		p->parent[1].mode = old->ce_mode;
-		hashcpy(p->parent[1].oid.hash, old->sha1);
+		oidcpy(&p->parent[1].oid, &old->oid);
 		show_combined_diff(p, 2, revs->dense_combined_merges, revs);
 		free(p);
 		return 0;
 	}
 
 	oldmode = old->ce_mode;
-	if (mode == oldmode && !hashcmp(sha1, old->sha1) && !dirty_submodule &&
+	if (mode == oldmode && !hashcmp(sha1, old->oid.hash) && !dirty_submodule &&
 	    !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
 		return 0;
 
 	diff_change(&revs->diffopt, oldmode, mode,
-		    old->sha1, sha1, 1, !is_null_sha1(sha1),
+		    old->oid.hash, sha1, 1, !is_null_sha1(sha1),
 		    old->name, 0, dirty_submodule);
 	return 0;
 }
@@ -392,7 +395,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,
 		struct diff_filepair *pair;
 		pair = diff_unmerge(&revs->diffopt, idx->name);
 		if (tree)
-			fill_filespec(pair->one, tree->sha1, 1, tree->ce_mode);
+			fill_filespec(pair->one, tree->oid.hash, 1,
+				      tree->ce_mode);
 		return;
 	}
 
@@ -408,7 +412,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,
 	 * Something removed from the tree?
 	 */
 	if (!idx) {
-		diff_index_show_file(revs, "-", tree, tree->sha1, 1, tree->ce_mode, 0);
+		diff_index_show_file(revs, "-", tree, tree->oid.hash, 1,
+				     tree->ce_mode, 0);
 		return;
 	}
 
diff --git a/diff.c b/diff.c
index 534c12e2..bba80665 100644
--- a/diff.c
+++ b/diff.c
@@ -2700,7 +2700,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
 	 * This is not the sha1 we are looking for, or
 	 * unreusable because it is not a regular file.
 	 */
-	if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode))
+	if (hashcmp(sha1, ce->oid.hash) || !S_ISREG(ce->ce_mode))
 		return 0;
 
 	/*
diff --git a/dir.c b/dir.c
index 0ea235f3..9e09bcbd 100644
--- a/dir.c
+++ b/dir.c
@@ -525,7 +525,7 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size,
 		return NULL;
 	if (!ce_skip_worktree(active_cache[pos]))
 		return NULL;
-	data = read_sha1_file(active_cache[pos]->sha1, &type, &sz);
+	data = read_sha1_file(active_cache[pos]->oid.hash, &type, &sz);
 	if (!data || type != OBJ_BLOB) {
 		free(data);
 		return NULL;
@@ -533,7 +533,7 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size,
 	*size = xsize_t(sz);
 	if (sha1_stat) {
 		memset(&sha1_stat->stat, 0, sizeof(sha1_stat->stat));
-		hashcpy(sha1_stat->sha1, active_cache[pos]->sha1);
+		hashcpy(sha1_stat->sha1, active_cache[pos]->oid.hash);
 	}
 	return data;
 }
@@ -713,7 +713,8 @@ static int add_excludes(const char *fname, const char *base, int baselen,
 				 !ce_stage(active_cache[pos]) &&
 				 ce_uptodate(active_cache[pos]) &&
 				 !would_convert_to_git(fname))
-				hashcpy(sha1_stat->sha1, active_cache[pos]->sha1);
+				hashcpy(sha1_stat->sha1,
+					active_cache[pos]->oid.hash);
 			else
 				hash_sha1_file(buf, size, "blob", sha1_stat->sha1);
 			fill_stat_data(&sha1_stat->stat, &st);
diff --git a/entry.c b/entry.c
index 519e0422..ce80d292 100644
--- a/entry.c
+++ b/entry.c
@@ -82,7 +82,7 @@ static int create_file(const char *path, unsigned int mode)
 static void *read_blob_entry(const struct cache_entry *ce, unsigned long *size)
 {
 	enum object_type type;
-	void *new = read_sha1_file(ce->sha1, &type, size);
+	void *new = read_sha1_file(ce->oid.hash, &type, size);
 
 	if (new) {
 		if (type == OBJ_BLOB)
@@ -127,7 +127,7 @@ static int streaming_write_entry(const struct cache_entry *ce, char *path,
 	if (fd < 0)
 		return -1;
 
-	result |= stream_blob_to_fd(fd, ce->sha1, filter, 1);
+	result |= stream_blob_to_fd(fd, ce->oid.hash, filter, 1);
 	*fstat_done = fstat_output(fd, state, statbuf);
 	result |= close(fd);
 
@@ -148,7 +148,8 @@ static int write_entry(struct cache_entry *ce,
 	struct stat st;
 
 	if (ce_mode_s_ifmt == S_IFREG) {
-		struct stream_filter *filter = get_stream_filter(ce->name, ce->sha1);
+		struct stream_filter *filter = get_stream_filter(ce->name,
+								 ce->oid.hash);
 		if (filter &&
 		    !streaming_write_entry(ce, path, filter,
 					   state, to_tempfile,
@@ -162,7 +163,7 @@ static int write_entry(struct cache_entry *ce,
 		new = read_blob_entry(ce, &size);
 		if (!new)
 			return error("unable to read sha1 file of %s (%s)",
-				path, sha1_to_hex(ce->sha1));
+				path, oid_to_hex(&ce->oid));
 
 		if (ce_mode_s_ifmt == S_IFLNK && has_symlinks && !to_tempfile) {
 			ret = symlink(new, path);
diff --git a/merge-recursive.c b/merge-recursive.c
index e3491268..e3db594d 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -382,7 +382,7 @@ static struct string_list *get_unmerged(void)
 		}
 		e = item->util;
 		e->stages[ce_stage(ce)].mode = ce->ce_mode;
-		hashcpy(e->stages[ce_stage(ce)].oid.hash, ce->sha1);
+		oidcpy(&e->stages[ce_stage(ce)].oid, &ce->oid);
 	}
 
 	return unmerged;
diff --git a/read-cache.c b/read-cache.c
index 491e52d1..31eddec5 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -161,7 +161,7 @@ static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
 	if (fd >= 0) {
 		unsigned char sha1[20];
 		if (!index_fd(sha1, fd, st, OBJ_BLOB, ce->name, 0))
-			match = hashcmp(sha1, ce->sha1);
+			match = hashcmp(sha1, ce->oid.hash);
 		/* index_fd() closed the file descriptor already */
 	}
 	return match;
@@ -178,7 +178,7 @@ static int ce_compare_link(const struct cache_entry *ce, size_t expected_size)
 	if (strbuf_readlink(&sb, ce->name, expected_size))
 		return -1;
 
-	buffer = read_sha1_file(ce->sha1, &type, &size);
+	buffer = read_sha1_file(ce->oid.hash, &type, &size);
 	if (buffer) {
 		if (size == sb.len)
 			match = memcmp(buffer, sb.buf, size);
@@ -202,7 +202,7 @@ static int ce_compare_gitlink(const struct cache_entry *ce)
 	 */
 	if (resolve_gitlink_ref(ce->name, "HEAD", sha1) < 0)
 		return 0;
-	return hashcmp(sha1, ce->sha1);
+	return hashcmp(sha1, ce->oid.hash);
 }
 
 static int ce_modified_check_fs(const struct cache_entry *ce, struct stat *st)
@@ -262,7 +262,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
 
 	/* Racily smudged entry? */
 	if (!ce->ce_stat_data.sd_size) {
-		if (!is_empty_blob_sha1(ce->sha1))
+		if (!is_empty_blob_sha1(ce->oid.hash))
 			changed |= DATA_CHANGED;
 	}
 
@@ -624,7 +624,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
 	unsigned char sha1[20];
 	if (write_sha1_file("", 0, blob_type, sha1))
 		die("cannot create an empty blob in the object database");
-	hashcpy(ce->sha1, sha1);
+	hashcpy(ce->oid.hash, sha1);
 }
 
 int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags, int force_mode)
@@ -691,7 +691,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 		return 0;
 	}
 	if (!intent_only) {
-		if (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT)) {
+		if (index_path(ce->oid.hash, path, st, HASH_WRITE_OBJECT)) {
 			free(ce);
 			return error("unable to index file %s", path);
 		}
@@ -705,7 +705,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 	/* It was suspected to be racily clean, but it turns out to be Ok */
 	was_same = (alias &&
 		    !ce_stage(alias) &&
-		    !hashcmp(alias->sha1, ce->sha1) &&
+		    !oidcmp(&alias->oid, &ce->oid) &&
 		    ce->ce_mode == alias->ce_mode);
 
 	if (pretend)
@@ -744,7 +744,7 @@ struct cache_entry *make_cache_entry(unsigned int mode,
 	size = cache_entry_size(len);
 	ce = xcalloc(1, size);
 
-	hashcpy(ce->sha1, sha1);
+	hashcpy(ce->oid.hash, sha1);
 	memcpy(ce->name, path, len);
 	ce->ce_flags = create_ce_flags(stage);
 	ce->ce_namelen = len;
@@ -1424,7 +1424,7 @@ static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *on
 	ce->ce_flags = flags & ~CE_NAMEMASK;
 	ce->ce_namelen = len;
 	ce->index = 0;
-	hashcpy(ce->sha1, ondisk->sha1);
+	hashcpy(ce->oid.hash, ondisk->sha1);
 	memcpy(ce->name, name, len);
 	ce->name[len] = '\0';
 	return ce;
@@ -1849,7 +1849,7 @@ static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
 	ondisk->uid  = htonl(ce->ce_stat_data.sd_uid);
 	ondisk->gid  = htonl(ce->ce_stat_data.sd_gid);
 	ondisk->size = htonl(ce->ce_stat_data.sd_size);
-	hashcpy(ondisk->sha1, ce->sha1);
+	hashcpy(ondisk->sha1, ce->oid.hash);
 
 	flags = ce->ce_flags & ~CE_NAMEMASK;
 	flags |= (ce_namelen(ce) >= CE_NAMEMASK ? CE_NAMEMASK : ce_namelen(ce));
@@ -2038,7 +2038,7 @@ static int do_write_index(struct index_state *istate, int newfd,
 			continue;
 		if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
 			ce_smudge_racily_clean_entry(ce);
-		if (is_null_sha1(ce->sha1)) {
+		if (is_null_oid(&ce->oid)) {
 			static const char msg[] = "cache entry has null sha1: %s";
 			static int allow = -1;
 
@@ -2285,7 +2285,7 @@ void *read_blob_data_from_index(struct index_state *istate, const char *path, un
 	}
 	if (pos < 0)
 		return NULL;
-	data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
+	data = read_sha1_file(istate->cache[pos]->oid.hash, &type, &sz);
 	if (!data || type != OBJ_BLOB) {
 		free(data);
 		return NULL;
diff --git a/rerere.c b/rerere.c
index aaadec17..5d083ca5 100644
--- a/rerere.c
+++ b/rerere.c
@@ -980,7 +980,8 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
 			break;
 		i = ce_stage(ce) - 1;
 		if (!mmfile[i].ptr) {
-			mmfile[i].ptr = read_sha1_file(ce->sha1, &type, &size);
+			mmfile[i].ptr = read_sha1_file(ce->oid.hash, &type,
+						       &size);
 			mmfile[i].size = size;
 		}
 	}
diff --git a/resolve-undo.c b/resolve-undo.c
index 468a2eb9..b40f3173 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -24,7 +24,7 @@ void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
 	if (!lost->util)
 		lost->util = xcalloc(1, sizeof(*ui));
 	ui = lost->util;
-	hashcpy(ui->sha1[stage - 1], ce->sha1);
+	hashcpy(ui->sha1[stage - 1], ce->oid.hash);
 	ui->mode[stage - 1] = ce->ce_mode;
 }
 
diff --git a/revision.c b/revision.c
index 8a29cb03..969b3d14 100644
--- a/revision.c
+++ b/revision.c
@@ -1275,7 +1275,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned flags)
 		if (S_ISGITLINK(ce->ce_mode))
 			continue;
 
-		blob = lookup_blob(ce->sha1);
+		blob = lookup_blob(ce->oid.hash);
 		if (!blob)
 			die("unable to add index blob to traversal");
 		add_pending_object_with_path(revs, &blob->object, "",
diff --git a/sha1_name.c b/sha1_name.c
index ca7ddd6f..e4404391 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -1435,7 +1435,7 @@ static int get_sha1_with_context_1(const char *name,
 			    memcmp(ce->name, cp, namelen))
 				break;
 			if (ce_stage(ce) == stage) {
-				hashcpy(sha1, ce->sha1);
+				hashcpy(sha1, ce->oid.hash);
 				oc->mode = ce->ce_mode;
 				free(new_path);
 				return 0;
diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c
index d1689248..e44430b6 100644
--- a/t/helper/test-dump-split-index.c
+++ b/t/helper/test-dump-split-index.c
@@ -23,7 +23,7 @@ int cmd_main(int ac, const char **av)
 	for (i = 0; i < the_index.cache_nr; i++) {
 		struct cache_entry *ce = the_index.cache[i];
 		printf("%06o %s %d\t%s\n", ce->ce_mode,
-		       sha1_to_hex(ce->sha1), ce_stage(ce), ce->name);
+		       oid_to_hex(&ce->oid), ce_stage(ce), ce->name);
 	}
 	printf("replacements:");
 	if (si->replace_bitmap)
diff --git a/tree.c b/tree.c
index 0089e52d..2b5a5a86 100644
--- a/tree.c
+++ b/tree.c
@@ -26,7 +26,7 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b
 	ce->ce_namelen = baselen + len;
 	memcpy(ce->name, base, baselen);
 	memcpy(ce->name + baselen, pathname, len+1);
-	hashcpy(ce->sha1, sha1);
+	hashcpy(ce->oid.hash, sha1);
 	return add_cache_entry(ce, opt);
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 11c37fbc..9238308f 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -625,7 +625,7 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info, con
 	ce->ce_mode = create_ce_mode(n->mode);
 	ce->ce_flags = create_ce_flags(stage);
 	ce->ce_namelen = len;
-	hashcpy(ce->sha1, n->oid->hash);
+	oidcpy(&ce->oid, n->oid);
 	make_traverse_path(ce->name, info, n);
 
 	return ce;
@@ -1287,7 +1287,7 @@ static int same(const struct cache_entry *a, const struct cache_entry *b)
 	if ((a->ce_flags | b->ce_flags) & CE_CONFLICTED)
 		return 0;
 	return a->ce_mode == b->ce_mode &&
-	       !hashcmp(a->sha1, b->sha1);
+	       !oidcmp(&a->oid, &b->oid);
 }
 
 
@@ -1393,7 +1393,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
 		/* If we are not going to update the submodule, then
 		 * we don't care.
 		 */
-		if (!hashcmp(sha1, ce->sha1))
+		if (!hashcmp(sha1, ce->oid.hash))
 			return 0;
 		return verify_clean_submodule(ce, error_type, o);
 	}
@@ -1665,7 +1665,7 @@ static void show_stage_entry(FILE *o,
 		fprintf(o, "%s%06o %s %d\t%s\n",
 			label,
 			ce->ce_mode,
-			sha1_to_hex(ce->sha1),
+			oid_to_hex(&ce->oid),
 			ce_stage(ce),
 			ce->name);
 }

^ permalink raw reply related

* [PATCH v2 00/20] object_id part 5
From: brian m. carlson @ 2016-09-05 20:07 UTC (permalink / raw)
  To: git
  Cc: Paul Tan, Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Jeff King, Johannes Schindelin, Jakub Narębski


This is the fifth in a series of series to convert from unsigned char [20] to
struct object_id.

This series converts many of the files in the builtin directory to use struct
object_id.  This gets us almost to the point where we can convert get_tree_entry
to use struct object_id, but not quite.  That function is used indirectly by
get_sha1, meaning that get_oid would have to completely replace it in order for
get_tree_entry to be converted.

However, this series tackles one of two major sources of object ID values: the
command line (the other, of course, being the refs code).  Converting several of
the builtin commands to use struct object_id as much as possible makes it easier
to convert other functions down the line.

Changes from v1:
* More clearly state that the Coccinelle-using patches also have a manual struct
  update.
* Convert the uninitialized constant in notes-merge.c.
* Convert one additional use of update_ref into update_ref_oid.

brian m. carlson (20):
  cache: convert struct cache_entry to use struct object_id
  builtin/apply: convert static functions to struct object_id
  builtin/blame: convert struct origin to use struct object_id
  builtin/log: convert some static functions to use struct object_id
  builtin/cat-file: convert struct expand_data to use struct object_id
  builtin/cat-file: convert some static functions to struct object_id
  builtin: convert textconv_object to use struct object_id
  streaming: make stream_blob_to_fd take struct object_id
  builtin/checkout: convert some static functions to struct object_id
  notes-merge: convert struct notes_merge_pair to struct object_id
  Convert read_mmblob to take struct object_id.
  builtin/blame: convert file to use struct object_id
  builtin/rm: convert to use struct object_id
  notes: convert init_notes to use struct object_id
  builtin/update-index: convert file to struct object_id
  sha1_name: convert get_sha1_mb to struct object_id
  refs: add an update_ref_oid function.
  builtin/am: convert to struct object_id
  builtin/commit-tree: convert to struct object_id
  builtin/reset: convert to use struct object_id

 builtin.h                        |   2 +-
 builtin/am.c                     | 140 +++++++++++++++++++--------------------
 builtin/apply.c                  |  94 +++++++++++++-------------
 builtin/blame.c                  |  76 ++++++++++-----------
 builtin/cat-file.c               |  70 ++++++++++----------
 builtin/checkout.c               |  70 ++++++++++----------
 builtin/commit-tree.c            |  20 +++---
 builtin/fsck.c                   |   4 +-
 builtin/grep.c                   |   3 +-
 builtin/log.c                    |  44 ++++++------
 builtin/ls-files.c               |   2 +-
 builtin/merge-index.c            |   2 +-
 builtin/read-tree.c              |   2 +-
 builtin/reset.c                  |  52 +++++++--------
 builtin/rm.c                     |  18 ++---
 builtin/submodule--helper.c      |   5 +-
 builtin/update-index.c           |  67 ++++++++++---------
 cache-tree.c                     |   4 +-
 cache.h                          |   4 +-
 diff-lib.c                       |  31 +++++----
 diff.c                           |   2 +-
 dir.c                            |   7 +-
 entry.c                          |   9 +--
 merge-recursive.c                |   8 +--
 notes-merge.c                    | 127 ++++++++++++++++++-----------------
 notes.c                          |  12 ++--
 read-cache.c                     |  24 +++----
 refs.c                           |   8 +++
 refs.h                           |   3 +
 rerere.c                         |   3 +-
 resolve-undo.c                   |   2 +-
 revision.c                       |   2 +-
 sha1_name.c                      |  20 +++---
 streaming.c                      |   4 +-
 streaming.h                      |   2 +-
 t/helper/test-dump-split-index.c |   2 +-
 tree.c                           |   2 +-
 unpack-trees.c                   |   8 +--
 xdiff-interface.c                |   8 +--
 xdiff-interface.h                |   3 +-
 40 files changed, 497 insertions(+), 469 deletions(-)


^ permalink raw reply

* [PATCH v2 02/20] builtin/apply: convert static functions to struct object_id
From: brian m. carlson @ 2016-09-05 20:07 UTC (permalink / raw)
  To: git
  Cc: Paul Tan, Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Jeff King, Johannes Schindelin, Jakub Narębski
In-Reply-To: <20160905200811.697889-1-sandals@crustytoothpaste.net>

There were several static functions using unsigned char arrays for SHA-1
values.  Convert them to use struct object_id.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 builtin/apply.c | 96 ++++++++++++++++++++++++++++-----------------------------
 1 file changed, 48 insertions(+), 48 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index ba0e75bf..76b16121 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3101,16 +3101,16 @@ static int apply_binary(struct apply_state *state,
 			struct patch *patch)
 {
 	const char *name = patch->old_name ? patch->old_name : patch->new_name;
-	unsigned char sha1[20];
+	struct object_id oid;
 
 	/*
 	 * For safety, we require patch index line to contain
 	 * full 40-byte textual SHA1 for old and new, at least for now.
 	 */
-	if (strlen(patch->old_sha1_prefix) != 40 ||
-	    strlen(patch->new_sha1_prefix) != 40 ||
-	    get_sha1_hex(patch->old_sha1_prefix, sha1) ||
-	    get_sha1_hex(patch->new_sha1_prefix, sha1))
+	if (strlen(patch->old_sha1_prefix) != GIT_SHA1_HEXSZ ||
+	    strlen(patch->new_sha1_prefix) != GIT_SHA1_HEXSZ ||
+	    get_oid_hex(patch->old_sha1_prefix, &oid) ||
+	    get_oid_hex(patch->new_sha1_prefix, &oid))
 		return error("cannot apply binary patch to '%s' "
 			     "without full index line", name);
 
@@ -3119,12 +3119,12 @@ static int apply_binary(struct apply_state *state,
 		 * See if the old one matches what the patch
 		 * applies to.
 		 */
-		hash_sha1_file(img->buf, img->len, blob_type, sha1);
-		if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix))
+		hash_sha1_file(img->buf, img->len, blob_type, oid.hash);
+		if (strcmp(oid_to_hex(&oid), patch->old_sha1_prefix))
 			return error("the patch applies to '%s' (%s), "
 				     "which does not match the "
 				     "current contents.",
-				     name, sha1_to_hex(sha1));
+				     name, oid_to_hex(&oid));
 	}
 	else {
 		/* Otherwise, the old one must be empty. */
@@ -3133,19 +3133,19 @@ static int apply_binary(struct apply_state *state,
 				     "'%s' but it is not empty", name);
 	}
 
-	get_sha1_hex(patch->new_sha1_prefix, sha1);
-	if (is_null_sha1(sha1)) {
+	get_oid_hex(patch->new_sha1_prefix, &oid);
+	if (is_null_oid(&oid)) {
 		clear_image(img);
 		return 0; /* deletion patch */
 	}
 
-	if (has_sha1_file(sha1)) {
+	if (has_sha1_file(oid.hash)) {
 		/* We already have the postimage */
 		enum object_type type;
 		unsigned long size;
 		char *result;
 
-		result = read_sha1_file(sha1, &type, &size);
+		result = read_sha1_file(oid.hash, &type, &size);
 		if (!result)
 			return error("the necessary postimage %s for "
 				     "'%s' cannot be read",
@@ -3164,10 +3164,10 @@ static int apply_binary(struct apply_state *state,
 				     name);
 
 		/* verify that the result matches */
-		hash_sha1_file(img->buf, img->len, blob_type, sha1);
-		if (strcmp(sha1_to_hex(sha1), patch->new_sha1_prefix))
+		hash_sha1_file(img->buf, img->len, blob_type, oid.hash);
+		if (strcmp(oid_to_hex(&oid), patch->new_sha1_prefix))
 			return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"),
-				name, patch->new_sha1_prefix, sha1_to_hex(sha1));
+				name, patch->new_sha1_prefix, oid_to_hex(&oid));
 	}
 
 	return 0;
@@ -3197,17 +3197,17 @@ static int apply_fragments(struct apply_state *state, struct image *img, struct
 	return 0;
 }
 
-static int read_blob_object(struct strbuf *buf, const unsigned char *sha1, unsigned mode)
+static int read_blob_object(struct strbuf *buf, const struct object_id *oid, unsigned mode)
 {
 	if (S_ISGITLINK(mode)) {
 		strbuf_grow(buf, 100);
-		strbuf_addf(buf, "Subproject commit %s\n", sha1_to_hex(sha1));
+		strbuf_addf(buf, "Subproject commit %s\n", oid_to_hex(oid));
 	} else {
 		enum object_type type;
 		unsigned long sz;
 		char *result;
 
-		result = read_sha1_file(sha1, &type, &sz);
+		result = read_sha1_file(oid->hash, &type, &sz);
 		if (!result)
 			return -1;
 		/* XXX read_sha1_file NUL-terminates */
@@ -3220,7 +3220,7 @@ static int read_file_or_gitlink(const struct cache_entry *ce, struct strbuf *buf
 {
 	if (!ce)
 		return 0;
-	return read_blob_object(buf, ce->oid.hash, ce->ce_mode);
+	return read_blob_object(buf, &ce->oid, ce->ce_mode);
 }
 
 static struct patch *in_fn_table(struct apply_state *state, const char *name)
@@ -3427,17 +3427,17 @@ static int load_preimage(struct apply_state *state,
 
 static int three_way_merge(struct image *image,
 			   char *path,
-			   const unsigned char *base,
-			   const unsigned char *ours,
-			   const unsigned char *theirs)
+			   const struct object_id *base,
+			   const struct object_id *ours,
+			   const struct object_id *theirs)
 {
 	mmfile_t base_file, our_file, their_file;
 	mmbuffer_t result = { NULL };
 	int status;
 
-	read_mmblob(&base_file, base);
-	read_mmblob(&our_file, ours);
-	read_mmblob(&their_file, theirs);
+	read_mmblob(&base_file, base->hash);
+	read_mmblob(&our_file, ours->hash);
+	read_mmblob(&their_file, theirs->hash);
 	status = ll_merge(&result, path,
 			  &base_file, "base",
 			  &our_file, "ours",
@@ -3506,7 +3506,7 @@ static int try_threeway(struct apply_state *state,
 			struct stat *st,
 			const struct cache_entry *ce)
 {
-	unsigned char pre_sha1[20], post_sha1[20], our_sha1[20];
+	struct object_id pre_oid, post_oid, our_oid;
 	struct strbuf buf = STRBUF_INIT;
 	size_t len;
 	int status;
@@ -3520,9 +3520,9 @@ static int try_threeway(struct apply_state *state,
 
 	/* Preimage the patch was prepared for */
 	if (patch->is_new)
-		write_sha1_file("", 0, blob_type, pre_sha1);
-	else if (get_sha1(patch->old_sha1_prefix, pre_sha1) ||
-		 read_blob_object(&buf, pre_sha1, patch->old_mode))
+		write_sha1_file("", 0, blob_type, pre_oid.hash);
+	else if (get_sha1(patch->old_sha1_prefix, pre_oid.hash) ||
+		 read_blob_object(&buf, &pre_oid, patch->old_mode))
 		return error("repository lacks the necessary blob to fall back on 3-way merge.");
 
 	fprintf(stderr, "Falling back to three-way merge...\n");
@@ -3535,7 +3535,7 @@ static int try_threeway(struct apply_state *state,
 		return -1;
 	}
 	/* post_sha1[] is theirs */
-	write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, post_sha1);
+	write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, post_oid.hash);
 	clear_image(&tmp_image);
 
 	/* our_sha1[] is ours */
@@ -3548,12 +3548,12 @@ static int try_threeway(struct apply_state *state,
 			return error("cannot read the current contents of '%s'",
 				     patch->old_name);
 	}
-	write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, our_sha1);
+	write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, our_oid.hash);
 	clear_image(&tmp_image);
 
 	/* in-core three-way merge between post and our using pre as base */
 	status = three_way_merge(image, patch->new_name,
-				 pre_sha1, our_sha1, post_sha1);
+				 &pre_oid, &our_oid, &post_oid);
 	if (status < 0) {
 		fprintf(stderr, "Failed to fall back on three-way merge...\n");
 		return status;
@@ -3564,9 +3564,9 @@ static int try_threeway(struct apply_state *state,
 		if (patch->is_new)
 			oidclr(&patch->threeway_stage[0]);
 		else
-			hashcpy(patch->threeway_stage[0].hash, pre_sha1);
-		hashcpy(patch->threeway_stage[1].hash, our_sha1);
-		hashcpy(patch->threeway_stage[2].hash, post_sha1);
+			oidcpy(&patch->threeway_stage[0], &pre_oid);
+		oidcpy(&patch->threeway_stage[1], &our_oid);
+		oidcpy(&patch->threeway_stage[2], &post_oid);
 		fprintf(stderr, "Applied patch to '%s' with conflicts.\n", patch->new_name);
 	} else {
 		fprintf(stderr, "Applied patch to '%s' cleanly.\n", patch->new_name);
@@ -3949,8 +3949,8 @@ static int check_patch_list(struct apply_state *state, struct patch *patch)
 	return err;
 }
 
-/* This function tries to read the sha1 from the current index */
-static int get_current_sha1(const char *path, unsigned char *sha1)
+/* This function tries to read the object ID from the current index */
+static int get_current_oid(const char *path, struct object_id *oid)
 {
 	int pos;
 
@@ -3959,11 +3959,11 @@ static int get_current_sha1(const char *path, unsigned char *sha1)
 	pos = cache_name_pos(path, strlen(path));
 	if (pos < 0)
 		return -1;
-	hashcpy(sha1, active_cache[pos]->oid.hash);
+	oidcpy(oid, &active_cache[pos]->oid);
 	return 0;
 }
 
-static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20])
+static int preimage_oid_in_gitlink_patch(struct patch *p, struct object_id *oid)
 {
 	/*
 	 * A usable gitlink patch has only one fragment (hunk) that looks like:
@@ -3987,14 +3987,14 @@ static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20
 	    (preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL &&
 	    starts_with(++preimage, heading) &&
 	    /* does it record full SHA-1? */
-	    !get_sha1_hex(preimage + sizeof(heading) - 1, sha1) &&
-	    preimage[sizeof(heading) + 40 - 1] == '\n' &&
+	    !get_oid_hex(preimage + sizeof(heading) - 1, oid) &&
+	    preimage[sizeof(heading) + GIT_SHA1_HEXSZ - 1] == '\n' &&
 	    /* does the abbreviated name on the index line agree with it? */
 	    starts_with(preimage + sizeof(heading) - 1, p->old_sha1_prefix))
 		return 0; /* it all looks fine */
 
 	/* we may have full object name on the index line */
-	return get_sha1_hex(p->old_sha1_prefix, sha1);
+	return get_oid_hex(p->old_sha1_prefix, oid);
 }
 
 /* Build an index that contains the just the files needed for a 3way merge */
@@ -4008,7 +4008,7 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
 	 * worth showing the new sha1 prefix, but until then...
 	 */
 	for (patch = list; patch; patch = patch->next) {
-		unsigned char sha1[20];
+		struct object_id oid;
 		struct cache_entry *ce;
 		const char *name;
 
@@ -4017,23 +4017,23 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
 			continue;
 
 		if (S_ISGITLINK(patch->old_mode)) {
-			if (!preimage_sha1_in_gitlink_patch(patch, sha1))
+			if (!preimage_oid_in_gitlink_patch(patch, &oid))
 				; /* ok, the textual part looks sane */
 			else
 				die("sha1 information is lacking or useless for submodule %s",
 				    name);
-		} else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
+		} else if (!get_sha1_blob(patch->old_sha1_prefix, oid.hash)) {
 			; /* ok */
 		} else if (!patch->lines_added && !patch->lines_deleted) {
 			/* mode-only change: update the current */
-			if (get_current_sha1(patch->old_name, sha1))
+			if (get_current_oid(patch->old_name, &oid))
 				die("mode change for %s, which is not "
 				    "in current HEAD", name);
 		} else
 			die("sha1 information is lacking or useless "
 			    "(%s).", name);
 
-		ce = make_cache_entry(patch->old_mode, sha1, name, 0, 0);
+		ce = make_cache_entry(patch->old_mode, oid.hash, name, 0, 0);
 		if (!ce)
 			die(_("make_cache_entry failed for path '%s'"), name);
 		if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
@@ -4211,7 +4211,7 @@ static void add_index_file(struct apply_state *state,
 		const char *s;
 
 		if (!skip_prefix(buf, "Subproject commit ", &s) ||
-		    get_sha1_hex(s, ce->oid.hash))
+		    get_oid_hex(s, &ce->oid))
 			die(_("corrupt patch for submodule %s"), path);
 	} else {
 		if (!state->cached) {

^ permalink raw reply related

* git commit -p with file arguments
From: Christian Neukirchen @ 2016-09-05 21:08 UTC (permalink / raw)
  To: git

Hi,

I noticed the following suprising behavior:

% git --version
git version 2.10.0

% git add bar
% git status -s 
A  bar
 M foo

% git commit -p foo
[stage a hunk]
...
# Explicit paths specified without -i or -o; assuming --only paths...
# On branch master
# Changes to be committed:
#       new file:   bar
#       modified:   foo
#

So why does it want to commit bar too, when I explicitly wanted to
commit foo only?

This is not how "git commit files..." works, and the man page says

            3.by listing files as arguments to the commit command, in which
           case the commit will ignore changes staged in the index, and
           instead record the current content of the listed files (which must
           already be known to Git);

I'd expect "git commit -p files..." to work like
"git add -p files... && git commit files...".

Thanks,
-- 
Christian Neukirchen  <chneukirchen@gmail.com>  http://chneukirchen.org


^ permalink raw reply

* [PATCH v1 0/2] Use CLOEXEC to avoid fd leaks
From: larsxschneider @ 2016-09-05 21:11 UTC (permalink / raw)
  To: git; +Cc: gitster, tboegi, Johannes.Schindelin, e, Lars Schneider

From: Lars Schneider <larsxschneider@gmail.com>

Use the CLOEXEC flag similar to 05d1ed61 to fix leaked file descriptors.

Patch 1/2 was contemplated by Junio here:
http://public-inbox.org/git/xmqq37lnbbpk.fsf@gitster.mtv.corp.google.com/

I followed Torsten's advice and renamed `git_open_noatime` to
`git_open_noatime_cloexec`:
http://public-inbox.org/git/20160830145429.GA11221@tb-raspi/

Patch 2/2 was part of my "Git filter protocol" series:
http://public-inbox.org/git/20160825110752.31581-14-larsxschneider@gmail.com/
(I kept the patch as-is but changed the commit messages slightly)

Thanks,
Lars

Lars Schneider (2):
  sha1_file: open window into packfiles with CLOEXEC
  read-cache: make sure file handles are not inherited by child
    processes

 builtin/pack-objects.c |  2 +-
 cache.h                |  2 +-
 pack-bitmap.c          |  2 +-
 read-cache.c           |  2 +-
 sha1_file.c            | 14 +++++++-------
 5 files changed, 11 insertions(+), 11 deletions(-)

--
2.10.0


^ permalink raw reply

* [PATCH v1 1/2] sha1_file: open window into packfiles with CLOEXEC
From: larsxschneider @ 2016-09-05 21:11 UTC (permalink / raw)
  To: git; +Cc: gitster, tboegi, Johannes.Schindelin, e, Lars Schneider
In-Reply-To: <20160905211111.72956-1-larsxschneider@gmail.com>

From: Lars Schneider <larsxschneider@gmail.com>

All processes that the Git main process spawns inherit the open file
descriptors of the main process. These leaked file descriptors can
cause problems.

Use the CLOEXEC flag similar to 05d1ed61 to fix the leaked file
descriptors.

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 builtin/pack-objects.c |  2 +-
 cache.h                |  2 +-
 pack-bitmap.c          |  2 +-
 sha1_file.c            | 14 +++++++-------
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 4a63398..a2b1fb6 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -718,7 +718,7 @@ static off_t write_reused_pack(struct sha1file *f)
 	if (!is_pack_valid(reuse_packfile))
 		die("packfile is invalid: %s", reuse_packfile->pack_name);
 
-	fd = git_open_noatime(reuse_packfile->pack_name);
+	fd = git_open_noatime_cloexec(reuse_packfile->pack_name);
 	if (fd < 0)
 		die_errno("unable to open packfile for reuse: %s",
 			  reuse_packfile->pack_name);
diff --git a/cache.h b/cache.h
index b780a91..ae79747 100644
--- a/cache.h
+++ b/cache.h
@@ -1089,7 +1089,7 @@ extern int write_sha1_file(const void *buf, unsigned long len, const char *type,
 extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags);
 extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
 extern int force_object_loose(const unsigned char *sha1, time_t mtime);
-extern int git_open_noatime(const char *name);
+extern int git_open_noatime_cloexec(const char *name);
 extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
 extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
 extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
diff --git a/pack-bitmap.c b/pack-bitmap.c
index b949e51..1b39e5d 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -266,7 +266,7 @@ static int open_pack_bitmap_1(struct packed_git *packfile)
 		return -1;
 
 	idx_name = pack_bitmap_filename(packfile);
-	fd = git_open_noatime(idx_name);
+	fd = git_open_noatime_cloexec(idx_name);
 	free(idx_name);
 
 	if (fd < 0)
diff --git a/sha1_file.c b/sha1_file.c
index 3045aea..c1701dc 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -356,7 +356,7 @@ void read_info_alternates(const char * relative_base, int depth)
 	int fd;
 
 	path = xstrfmt("%s/info/alternates", relative_base);
-	fd = git_open_noatime(path);
+	fd = git_open_noatime_cloexec(path);
 	free(path);
 	if (fd < 0)
 		return;
@@ -550,7 +550,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
 	struct pack_idx_header *hdr;
 	size_t idx_size;
 	uint32_t version, nr, i, *index;
-	int fd = git_open_noatime(path);
+	int fd = git_open_noatime_cloexec(path);
 	struct stat st;
 
 	if (fd < 0)
@@ -956,7 +956,7 @@ static int open_packed_git_1(struct packed_git *p)
 	while (pack_max_fds <= pack_open_fds && close_one_pack())
 		; /* nothing */
 
-	p->pack_fd = git_open_noatime(p->pack_name);
+	p->pack_fd = git_open_noatime_cloexec(p->pack_name);
 	if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
 		return -1;
 	pack_open_fds++;
@@ -1459,9 +1459,9 @@ int check_sha1_signature(const unsigned char *sha1, void *map,
 	return hashcmp(sha1, real_sha1) ? -1 : 0;
 }
 
-int git_open_noatime(const char *name)
+int git_open_noatime_cloexec(const char *name)
 {
-	static int sha1_file_open_flag = O_NOATIME;
+	static int sha1_file_open_flag = O_NOATIME | O_CLOEXEC;
 
 	for (;;) {
 		int fd;
@@ -1505,7 +1505,7 @@ static int open_sha1_file(const unsigned char *sha1)
 	struct alternate_object_database *alt;
 	int most_interesting_errno;
 
-	fd = git_open_noatime(sha1_file_name(sha1));
+	fd = git_open_noatime_cloexec(sha1_file_name(sha1));
 	if (fd >= 0)
 		return fd;
 	most_interesting_errno = errno;
@@ -1513,7 +1513,7 @@ static int open_sha1_file(const unsigned char *sha1)
 	prepare_alt_odb();
 	for (alt = alt_odb_list; alt; alt = alt->next) {
 		fill_sha1_path(alt->name, sha1);
-		fd = git_open_noatime(alt->base);
+		fd = git_open_noatime_cloexec(alt->base);
 		if (fd >= 0)
 			return fd;
 		if (most_interesting_errno == ENOENT)
-- 
2.10.0


^ permalink raw reply related

* [PATCH v1 2/2] read-cache: make sure file handles are not inherited by child processes
From: larsxschneider @ 2016-09-05 21:11 UTC (permalink / raw)
  To: git; +Cc: gitster, tboegi, Johannes.Schindelin, e, Lars Schneider
In-Reply-To: <20160905211111.72956-1-larsxschneider@gmail.com>

From: Lars Schneider <larsxschneider@gmail.com>

This fix prepares a series with the goal to avoid launching a new
clean/smudge filter process for each file that is filtered. A new
long running filter process is introduced that is used to filter all
files in a single Git invocation.

Consider the case of a file that requires filtering and is present in
branch A but not in branch B. If A is the current HEAD and we checkout B
then the following happens:

1. ce_compare_data() opens the file
2.   index_fd() detects that the file requires to run a clean filter and
     calls index_stream_convert_blob()
4.     index_stream_convert_blob() calls convert_to_git_filter_fd()
5.       convert_to_git_filter_fd() calls apply_filter() which creates a
         new long running filter process (in case it is the first file
         of this kind to be filtered)
6.       The new filter process inherits all file handles. This is the
         default on Linux/OSX and is explicitly defined in the
         `CreateProcessW` call in `mingw.c` on Windows.
7. ce_compare_data() closes the file
8. Git unlinks the file as it is not present in B

The unlink operation does not work on Windows because the filter process
has still an open handle to the file. On Linux/OSX the unlink operation
succeeds but the file descriptors still leak into the child process.

Fix this problem by opening files in read-cache with the CLOEXEC flag to
ensure that the file descriptor does not remain open in a newly spawned
process similar to 05d1ed61.

Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 read-cache.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/read-cache.c b/read-cache.c
index 491e52d..02f74d3 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -156,7 +156,7 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
 static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
 {
 	int match = -1;
-	int fd = open(ce->name, O_RDONLY);
+	int fd = open(ce->name, O_RDONLY | O_CLOEXEC);
 
 	if (fd >= 0) {
 		unsigned char sha1[20];
-- 
2.10.0


^ permalink raw reply related

* [RFCv3] Proposed questions for "Git User's Survey 2016", take three
From: Jakub Narębski @ 2016-09-05 21:27 UTC (permalink / raw)
  To: git
  Cc: Doug Rathbone, David Bainbridge, Stefan Beller, Eric Wong,
	Andrew Ardill, W. David Jarvis
In-Reply-To: <ae804c55-d145-fc90-e1a9-6ebd6c60453a@gmail.com>

Hello,

As I wrote previously, I am thinking about returning to doing the
Git User's Survey this year.

  Message-ID: <577E6F32.7020007@gmail.com>

  https://marc.info/?l=git&m=146790381602547&w=2
  https://public-inbox.org/git/577E6F32.7020007%40gmail.com/

In this email I'd like to propose the revised list of questions (and
answers) for Git User's Survey 2016, following comments to the previous
revisions, starting with

  Message-ID: <91a2ffbe-a73b-fbb9-96da-9aea4d439e5a@gmail.com>

  https://public-inbox.org/git/91a2ffbe-a73b-fbb9-96da-9aea4d439e5a@gmail.com/


Below is my third, and probably final proposal.  You can see the survey
in work at (there might be some slight differences from what's below)

  https://survs.com/survey/kn2bpu4p9d

NOTE: This is a *test channel*, all responses will be deleted.


The survey is currently planned to be open (after a bit of delay)
from  10 September 2016  to  20 October 2016.

I'd like to ask also about announcing the survey as widely as possible.
Please reply if you think of some channel, or of you could announce
it yourself.  Thanks in advance.


If you want to do this survey "in house", you can ask for a separate
channel (a separate survey URL).  After the survey ends, I'll send 
anonymous responses from that channel in Excel and CSV formats.

There also will be anonymous, JavaScript- and cookie-less channel;
at the cost that you cannot go back and change or add to your response.
----------------------------------------------------------------------------
There are 50 questions in this survey.


#### About you

01. What country do you live in? (Country of residence, in English)
    (free-form single line)

02. How old are you (in years)?
    (single number)

03. What is your gender?
    (single choice)

  *  Man
  *  Woman
  *  Other
  *  Prefer to not disclose

04. How would you describe your occupation / role as Git user?
    (multiple choice with other, limit to 3 selections)

  + Developer
  + Programmer
  + Engineer
  + Analyst
  + Manager / Leader
  + Maintainer / Reviewer / Sub-maintainer
  + DevOps
  + Administrator
  + Designer
  + Artist / Writer
  + Tester / QA
  + Expert
  + Student
  + Researcher
  + Teacher
  + Other, please specify

05. Have you ever contributed to Git project (code, documentation, i18n, etc.)?
    (single choice)

  * Yes
  * No
  * Maybe, don't remember
  * Plan to, soon

06. Have you ever reviewed contribution to Git project?
    (single choice)

  * Yes
  * No
  * Maybe, don't remember
  * Plan to, soon
  * Only spelling corrections, or correctness of translation

07. What's stopping you from contributing to Git?
    What was hardest / most difficult when contribution to Git?
    (free-text essay question)


#### Getting started with Git

08. Have you found Git easy to learn?
    (single choice)

  * Very easy
  * Easy
  * Reasonably easy (average)
  * Hard
  * Very hard

09. Have you found Git easy to use?
    (single choice)

  * Very easy
  * Easy
  * Reasonably easy (average)
  * Hard
  * Very hard

10. Rate your own proficiency with Git
    (single choice, rating)

  1. novice
  2. casual, needs advice
  3. everyday use
  4. can offer advice
  5. know it very well

Description:
~~~~~~~~~~~~
You can think of it as 1-5 numerical grade of your proficiency in Git.



11. Which Git version(s) are you using?
   (multiple choice, with other)

 + I don't remember and cannot check the version
 + pre 2.0
 + 2.0.x to 2.4.x
 + 2.5.x
 + 2.6.x
 + 2.7.x
 + 2.8.x
 + 2.9.x
 + 2.10.x or newer
 + 2.10.x-rcN version (release candidate)
 + minor (maintenance) release 1.x.y.z
 + 'master' branch of official git repository
 + 'next' branch of official git repository
 + version from msysGit / Git for Windows fork repository
 + alternate Git implementation (JGit and similar)

 + other, please specify


#### Getting and updating Git

12. On which operating system(s) do you use Git?
    (multiple choice, with other)

 + GNU/Linux
 + MS Windows
 + macOS
 + *BSD (FreeBSD, OpenBSD, NetBSD, etc.)
 + Android
 + iOS
 + other Unix

 + other operating system, please specify

13. How do/did you obtain Git (install and/or upgrade)?
    (multiple choices, with other)

  + binary package
  + source package or script (automatic compiling)
  + source tarball/archive (extract, make, make install)
  + pull from repository, and compiled
  + bundled with GUI or other tool
  + preinstalled / sysadmin job / I don't know

  + other, please specify (if none of the above apply)

14. How often do you upgrade Git?
    (multiple choice)

  + use 'master' or 'next' version, and/or pre-release
  + as soon as new version is released
  + when there is new binary package / distribution package
  + when updating distribution / system
  + around every month, or more often
  + around every 6 months or more often
  + update from time to time, cannot say how often
  + I use what is installed on system


#### How do you use Git

15. What kind of projects etc. do you use Git for?
    (multiple choice, with other)

  + work and work-related projects
  + unpaid projects

  + closed-source projects
  + open-source development, public domain, and published & unlicensed
  + private (unpublished), in house projects

  + other (please specify)

16. I use Git for (check all that apply):
    (multiple choice, with other)

  + code (programming) and its documentation
  + data, documents, static assets (without code)

  + sharing data or synchronization
  + managing configuration files
  + backup
  + frontend / fat-client to other SCM (e.g. git-svn, git-p4)

  + other (please specify)

17. What kind of Git tools do you use?
    (multiple choice, with other)

  + editor/IDE VC integration (e.g. EGit (for Eclipse), TextMate bundle, magit (for GNU Emacs))
  + build tool integration (e.g. git plugin for Maven, gitbuilder, Parabuild)
  + continuous integration (CI) (e.g. cidaemon)
  + commit notification tools (e.g. irker, git-notify)
  + filemanager / shell extension (e.g. git-cheetah, TortoiseGit, Git Extension)
  + filesystem interface (e.g. gitfs, figfs)
  + graphical history viewer/browser (e.g. gitk; might be a part of GUI tool)
  + graphical commit tool (e.g. git-gui; might be a part of GUI tool)
  + graphical diff and/or merge tool (e.g. Kompare, Meld; might be a part of GUI tool)
  + graphical blame or pickaxe tool (e.g. 'git gui blame'; might be a part of editor plugin)
  + tool to manage git repositories (e.g. Gitolite)
  + git-instaweb, or self-hosted web interface (e.g. gitweb, cgit)
  + self-hosted project hosting solution / software forge (e.g. GitLab, GitHub Enterprise, Phabricator)
  + self-hosted code review or audit system (e.g. Gerrit, Differential)
  + patch or patch series management interface (e.g. StGit, Guilt, git-series)
  + tracking some files out-of-band, large files handling (e.g. git-LFS, git-annex, git-media)
  + storing metadata (e.g. metastore, gitperms, git-cache-meta)
  + managing composite repositories (e.g. git-stree, gitslave, repo)
  + command line tab-completion, or equivalent (e.g. git-completion.sh)
  + shell prompt, or widget, desklet, etc. (e.g. git-prompt / __git_ps1(), git-radar)
  + git aware pager, or syntax highlighter (e.g. tig, diff-highlight)
  + credentials helper, or askpass wrapper (e.g. wincred, winstore, cache)
  + remote helper to store repository (e.g. FTP, Amazon S3, Dropbox)
  + remote helper to interact with foreign repositories (e.g. git-hg)

  + my own scripts (for daily use)
  + my own scripts (for special tasks)

  + other kind, please specify

18. List git tools that you are using, one per line, or as comma separated list
    (textarea)

19. How often do you use Git command line (and other command line tools)?
    (single-choice, rating-like)

  * never
  * rarely (less often than other tools)
  * average, or about average
  * cannot say how often
  * often (more often than other tools)
  * only (always)


#### Git hosting sites and software forges

18. Which git hosting site(s) do you use for your project(s)?
    Please check only hosting sites where you publish/push to (with git)
    (multiple choice, with other)

  + GitHub
  + Bitbucket
  + GitLab

  + SourceForge
  + Savannah or Gna!
  + CodePlex

  + Assembla
  + Beanstalk
  + CloudForge (formetly Codesion)
  + Codebase
  + Deveo
  + Unfuddle

  + git hosting site for related projects (e.g. OLPC, freedesktop.org)
  + company internal / self-hosted

  + other site, please specify

21. If you, your project or your company self-hosts Git repositories,
    what Git repository management tools do they use?
    (multiple choice, assuming mostly single selected, with other)

  + git-shell
  + Gitolite
  + Gitosis (DEPRECATED)

  + Gerrit

  + Kallithea
  + Rhodecode
  + Phabricator

  + Bitbucket Server (Atlassian)
  + GitHub Enterprise
  + GitLab Community Edition (OSS)
  + GitLab Enterprise Edition
  + Deveo On-Premises

  + GitPrep
  + Girocco (repo.or.cz)

  + don't use self-hosted / on-premises
  + other, please specify

22. Do you use paid git hosting, and if so, why?
    (multiple choice, with other)

  * N/A (don't use paid git hosting)
  * private or team-limited repositories
  * increased limits (repository size, number of repositories)
  * paid support / help
  * extra features compared to free plan / free hosting
  * other, please specify


#### Interacting with other repositories, git workflows

23. How do you fetch/get changes from upstream repositories
    and/or other developers?
    (multiple choice, with other)

  + git protocol        (e.g. git://git.example.com/repo.git)
  + ssh                 (e.g. ssh+git://git.example.com/repo.git,
                              git.example.com:/srv/scm/repo.git)
  + http(s)             (e.g. http://git.example.com/repo.git)
  + rsync (DEPRECATED)  (e.g. rsync://git.example.com/repo.git)
  + filesystem          (e.g. /path/to/repo.git, file:///path/to/repo.git)
  + applying patches    (e.g. git-am from emails, or other source)
  + via git-bundle
  + foreign SCM (fat-client or remote helper, e.g. git-svn, git-p4, gitifyhg)

  + Other, please specify

24. How do you publish/propagate your changes?
    (multiple choice, with other)

  + push via SSH
  + push via HTTP / HTTPS
  + push via git protocol (not available y default, NOT RECOMMENDED)
  + push (unknown transport)
  + pull request (+ any form of announcement / notification)
  + format-patch + email
  + format-patch + other (e.g. reviewboard, issue tracker or forum)
  + git bundle

  + git-svn (to Subversion repository)
  + git-p4 (to Perforce repository)
  + foreign SCM interface, or remote helper (other than mentioned above)

  + other - please specify

25. What git workflow(s) is used by projects in which development you participate?
    (multiple choice, with other)

  + single developer, only private repository (no interaction)

  + centralized workflow (push to common repository)
  + branched centralized (push to different branches in common repository)
  + peer-to-peer workflow (all repositories roughly equal)
  + integration-manager workflow (maintainer pulls/applies patches to "blessed" repository))
  + dictator and lieutenants workflow (hierarchical workflow)
  + using collaborative code review tool, e.g. Gerrit

  + other workflow, please explain
 
References:
~~~~~~~~~~~
 [1] https://git-scm.com/book/en/Distributed-Git-Distributed-Workflows
 [2] https://git-scm.com/about/distributed
 [3] https://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html
 [4] https://gerrit-documentation.storage.googleapis.com/Documentation/2.12.3/intro-quick.html


26. What types of branches can be found in your repositories?
    (repositories you use or are contributing to)
    (multiple choice, with other)

  + there is only a single branch
  + development/graduation branches (master/stable, next/devel/unstable etc.)
  + per-release maintenance branches (or release branches)
  + proposed-updates integration testing and WIP publish branch

  + bugfix / hotfix branches (topic branches for bug fixes)
  + release branches (for preparing a new release)
  + other short-lived topic / feature branches

  + orphan branches (with disconnected history, e.g. gh-pages, todo)

  + other types and uses, please describe


27. How do you integrate changes from others?
    (multiple choice, with other)

  + merge  (includes 'git pull')
  + rebase (includes 'git pull --rebase')
  + reapply (e.g. git-am from patches)
  + git-imerge (third-party tool)

  + git mergetool, or graphical merge tool directly
  + graphical rebase tool
  + custom merge driver (e.g. to merge GNU ChangeLogs)

  + other, please specify


28. How do you sign your Git repositories?
    (multiple choice, with other)

  + digital certificate of origin ("Signed-off-by:")

  + signed tags
  + signed commits
  + signed merges (merging signed tags)
  + signed pushes

  + other way, please specify


#### How you use Git

29. Which of the following Git features do you use?
    (multiple choice, with other)

  + end-of-line conversion (crlf or eol)
  + custom diff/merge driver
  + textconv
  + other gitattributes (e.g. clean/smudge filter)

  + word diff
  + merge strategy options (e.g. -Xrenormalize)

  + submodules (subprojects)
  + subtrees / subtree merge (e.g. git-subtree, git-stree)

  + partial (sparse) checkout
  + shallow clone (e.g. "git clone --depth=<n>")

  + multiple worktrees (e.g. git-worktree)

  + searching history for commit message and metadata (e.g. "git log --grep")
  + searching changes in history, pickaxe search ("git log -S" and "git log -G")
  + finding bugs in history with bisect (also "git bisect run <script>")

  + tracking code movement with git-blame ("git blame -M", "git gui blame", etc.)
  + history of lines ("git log -L")

  + detaching HEAD (e.g. "git checkout --detach", "git checkout <tag>")
  + orphan branches, with disconnected history (gh-pages, todo, man, etc.)
  + merging independent histories, joining different projects together
    (outside subtree merge)

  + alternates mechanism (sharing object database)
  + stash and autostash (also "git stash --keep-index")
  + commit message templates, and/or commit-related hooks
  + interactive commit / per-hunk comitting / partial commit / splitting commits
  + interactive rebase, fixup commits (small scale history editing)
  + git-filter-branch or equivalent, like BFG Repo Cleaner (large history rewriting)
  + committing with dirty tree (keeping some changes uncommitted)
  + reflog (including @{1}, @{yesterday}, @{-1} / -, 'git log -g')

  + client-side hooks (e.g. pre-commit)
  + server-side hooks (e.g. post-receive)

  + git-aware shell prompt
  + git aliases, shell aliases for git, or own git scripts

  + one-way interaction with other SCMs (from SCM to git)
  + two-way interaction with other SCMs (from SCM to git, from git to SCM)

  + object overlays (git replace or grafts)
  + object annotation (git notes)

  + other, please specify


30. Describe what features would you like to have in Git
    (free form, essay length / textarea)

31. What tool do you use to create new commits?
    (matrix)

 Columns: never / rarely / often / always
 ----------------------------------------
  - command line				
  - graphical commit tool (GUI)				
  - IDE/editor integration				
  - filemanager extension				
  - web interface				
  - other kind of tool				

32. What do you use submodules (or their equivalent, like subtree) for?
    (multiple choice, with other)

  + I don't use submodules or subtrees
  + planning to use submodules
  + for dependency management (including dependencies)
  + to import repositories maintained by others (in subdirectory)
  + for your own (or your organization's) code shared between different projects
  + to separate large and/or many files for performance reasons
  + to separate data which you don't want (or aren't allowed) to disclose
  + to separate code whose copyright we do not own, or with different licensing
  + to manage access to different parts of repository

  + other purpose, please specify


#### Other version control systems

33. What other centralized, local or per-file version control systems (SCM)
    do you use beside Git?
   (multiple choice, with other)

  + I don't use any centralized or local version control system

  + PVCS
  + SCCS
  + RCS

  + CVS
  + Subversion

  + Perforce
  + ClearCase
  + AccuRev SCM
  + StarTeam
  + Visual SourceSafe
  + Vault
  + Team Foundation Server
  + Visual Studio Team System / ALM
  + Rational Team Concert

  + other centralized SCM, please specify


34. What other distributed version control systems
    do you use or used beside Git?
   (multiple choice, with other)

  + I don't use any version control system beside Git

  + Bazaar (bzr)
  + Mercurial (hg)
  + Monotone
  + Darcs
  + SVK
  + Fossil
  + Veracity

  + BitKeeper
  + Code Co-op
  + TeamWare
  + Plastic SCM
  + Veracity

  + other, please specify


35. How does Git compare to other SCM tools that you have used?
    (single choice, rating)

Git is ____ that other version control systems I have used.

 * better
 * equal (comparable)
 * it depends (in some matters better, in some matters worse)
 * worse
 * cannot compare (have not used anything beside Git)


#### What you think of Git?

36. Overall, how happy are you with Git?
    (single choice, rating)

  # hate it
  * unhappy
  * not so happy
  # neutral
  * happy
  * very happy
  * completely ecstatic

37. In your opinion, which areas in Git needs improvement?
    Please state your preference.
    (matrix)

   Columns: don't care / don't need / a little / some / much
   ---------------------------------------------------------
 + user-interface (UI and UX)
 + core documentation
 # messages, error messages, advices
 + performance
 * portability
 + more features
 + tools (e.g. GUI)
 + localization (translation) of messages
 # translated documentation (manpages)
 * community (mailing list)
 * community (IRC)	

38. What do you like most about Git? (optional)
   (free-text, essay length, textarea)
 
39. What do you hate about Git? (optional)
   (free-text, essay length, textarea)


#### Other tools

40. How do you read and answer email (check all that apply)?
    (multiple choice)

  + GUI client (e.g. Outlook, Thunderbird, Evolution, KMail)
  + console client (e.g. pine, alpine, mutt)
  + webmail or web client (e.g. GMail, Hotmail; HyperKitty)
  + phone app (e.g. K-9 Mail, Airmail, CloudMagic)
  + I don't use email at all

41. Which of the decentralized/federated systems do you use
    or are interested in?
   (multiple choice, with other)

  + IPFS
  + PGP / GPG
  + Tor
  + diaspora*
  + Bitcoin, Litecoin, Etherium, etc.
  + tent.io
  + XMPP / Jabber
  + OMEMO
  + Matrix.org
  + pump.io
  + other, please specify

42. Which of IDEs and programmer's editors do you use [with Git]?
    (multiple choice, with other)

  + Visual Studio
  + Eclipse
  + NetBeans
  + Xcode
  + IntelliJ IDEA / PhpStorm / WebStorm
  + KDevelop or Qt Designer
  + Anjuta
  + Android Studio

  + Sublime Text
  + TextMate
  + Emacs
  + Vim
  + Atom
  + Brackets
  + Geany
  + Notepad++

  + other IDE or editor, please specify


43. Which of the programming languages are you proficient with?
    (multiple choices, with other)

  + C
  + C++
  + C#
  + Java
  + VisualBasic.NET 
  + Objective-C

  + Python
  + Perl
  + PHP
  + JavaScript
  + Ruby
  + shell script

  + CSS, LESS, SASS etc.
  + HTML, HTML5
  + TeX, LaTeX, ConTeXt
  + SQL

  + Go
  + Rust
  + Swift
  + Scala
  + Haskell
  + OCaml

  + other, please specify


#### Documentation. Getting help.

44. How useful have you found the following forms of Git documentation?
    (matrix)

  Columns: never used / not useful / somewhat / useful
 ------------------------------------------------------
 + help distributed with git (manpages, tutorials, guides, etc.)
 + "Pro Git" book
 + Git Wiki
 + Git Reference site
 + hosting site tutorials and help, etc.
 + 'git' section of StackOverflow Documentation
 + other on-line help
 + printed books (or ebooks)

Description:
~~~~~~~~~~~~
* help distributed with Git includes their online version:
  - https://git.github.io/htmldocs/git.html
  - https://git-scm.com/docs/
  - https://www.kernel.org/pub/software/scm/git/docs/
* Git Wiki was to be found at http://git.wiki.kernel.org
* Git Reference site can be found at http://gitref.org
* StackOverflow Documentation refers to http://stackoverflow.com/documentation/git
* "Pro Git" can be found at https://git-scm.com/book and https://progit.org
* hosting sites tutorials include
  - https://help.github.com/
  - https://www.atlassian.com/git/
  - https://www.git-tower.com/learn/git/ebook
* help distributed with git include manpages, manual, tutorials, HOWTO,
  release notes, technical documentation, contrib/examples/


45. How useful have you found the following kinds of Git documentation?
    (matrix)

  Columns: never used / not useful / somewhat / useful
  ----------------------------------------------------
 + in-command (command messages)
 + command manpages
 + concept manpages (e.g. gitcli, gitworkflows)
 + tutorials
 + technical documentation
 + contrib/examples
 + "The Git User's Manual"				

 + "Pro Git"				
 + other printed books (or ebooks)


46. What [channel(s)] do you use to request/get help about Git [(if any)]?
   (multiple choice, with other)

  + git mailing list (git@vger.kernel.org)
  + "Git for Human Beings" Google Group
  + Git for Windows mailing list / Google Group
  + IRC (#git)
  + IRC (other git/SCM related, e.g. #github)
  + IRC (other than above)
  + request in blog post or on wiki
  + asking git expert/git guru/colleague/friend
  + project mailing list, or IRC, or forum
  + Twitter or other microblogging platform
  + instant messaging (IM) like XMPP/Jabber
  + StackOverflow or other StackExchange site
  + search specific site or whole web (e.g. with Google)

  + find and read book or ebook
  + watch an instructional video or course
  + attend a seminar, webinar or lecture about Git (interactively)

  + N/A (didn't request help about Git)

  + other (please specify)


47. Which books about Git have you read and recommend, or plan to read?
    (multiple choice, with other)

 + "Pragmatic Version Control Using Git", by Travis Swicegood (2008)
 + "Pragmatic Guide to Git", by Travis Swicegood (2010)
 + "Version Control by Example", by Eric Sink (2011)
 + "Version Control with Git", by by Jon Loeliger and Matthew McCullough
   (1st ed. 2009, 2nd ed. 2012)
 + "Git: Version Control for Everyone", by Ravishankar Somasundaram
   (2013)
 + "Pro Git", by Scott Chacon and Ben Straub (1st ed. 2009, 2nd ed. 2014)
 + "Git Version Control Cookbook", by Aske Olsson and Rasmus Voss (2014)
 + "Git in Practice", by Mike McQuaid (2014)
 + "Git for Teams", by Emma Hogbin Westby (2015)
 + "Git Essentials", by Ferdinando Santacroce (2015)
 + "Mastering Git", by Jakub Narębski (2016)



#### About this survey. Git news. Open forum.

48. How did you hear about this Git User's Survey? ===
    (single choice, with other)

 * git mailing list
 * git-related mailing list (e.g. msysGit, Git for Human Beings)
 * mailing list or forum of some project
 * #git IRC channel topic
 * announcement on IRC channel
 * git homepage
 * git wiki
 * git hosting site (or blog related to such site)
 * software-related web site
 * news or social news site (e.g. LWN.net, Digg, Reddit)
 * blog (or blog planet)
 * other kind of web site
 * Twitter or other microblogging platform

 * other - please specify

49. How do you hear about git related news 
    (such as new releases and community events)?
    (multiple choice, with other)

  + I wasn't aware there was any news
  + I don't read any news, but I'm aware of it
  + through news aggregation sites (such as reddit or hacker news)
  + from a newsletter (such as Git Rev News)
  + through a watched blog (such as GitHub Blog)
  + announcement section in news site (such as LWN.net)
  + RelNotes file(s) in git sources
  * from a mailing list (such as the git developer or the git for windows list)
  * other, please specify

50. What other comments or suggestions do you have,
    that are not covered by the questions above?
    (free-form / essay length / textarea)

-- 
Jakub Narębski





^ permalink raw reply

* Re: [PATCH] stash: allow ref of a stash by index
From: Øystein Walle @ 2016-09-05 21:46 UTC (permalink / raw)
  To: Jeff King
  Cc: Aaron M Watson, Git, Jon Seymour, David Caldwell,
	Ævar Arnfjörð Bjarmason, David Aguilar,
	Alex Henrie
In-Reply-To: <20160904015209.ba6arov46ntr2ouq@sigill.intra.peff.net>

Hi, guys

I like this idea. It makes stash easier and quicker to use, and it
"hides" the fact that it uses the reflog for keeping track of the made
stashes. *Not* to say I discourage interested people from peeking under
the hood. I just think it's nice to sometimes think of the stash as a
separate concept instead of being built on top of strange merge
commits constructed in temporary indexes :)

The bash-specific code is a no-go, so here's a way to do it in a way
that I think is in line with Git's code style for shell scripts. I took
the liberty of removing the '|| exit 1' since the rev is verified later
on anyway, as can be seen in the last piece of context. That way the
argument munging can be done at a later stage where we don't have to
loop over multiple ones. The first rev-parse's purpose is just to apply
--sq.

(Besides, the only way to do it at the top like in the original patch
was   for arg in bleh "$@"   where bleh is a marker to indicate that the
positional arguments should be cleared in a separate case branch so that
they can be rebuilt with multiple invocations of set later. Not pretty,
in my opinion.)

Regards,
Øsse

diff --git a/git-stash.sh b/git-stash.sh
index 826af18..b026288 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -384,7 +384,7 @@ parse_flags_and_rev()
     i_tree=
     u_tree=

-    REV=$(git rev-parse --no-flags --symbolic --sq "$@") || exit 1
+    REV=$(git rev-parse --no-flags --symbolic --sq "$@" 2>/dev/null)

     FLAGS=
     for opt
@@ -422,6 +422,15 @@ parse_flags_and_rev()
         ;;
     esac

+    case "$1" in
+        *[!0-9]*)
+            :
+        ;;
+        *)
+            set -- "${ref_stash}@{$1}"
+        ;;
+    esac
+
     REV=$(git rev-parse --symbolic --verify --quiet "$1") || {
         reference="$1"
         die "$(eval_gettext "\$reference is not a valid reference")"

^ permalink raw reply related

* [PATCH 0/5] handle tag recursion in pack-objects --include-tag
From: Jeff King @ 2016-09-05 21:51 UTC (permalink / raw)
  To: git

If you have a tag of a tag of a commit, and the middle tag isn't
otherwise reachable, then "pack-objects --include-tag" will not include
the middle tag, and certain invocations of "clone" will fail. See the
final patch below for the gory details.

The first five patches are just test cleanup and modernization in
preparation (though note that the 3rd one actually fixes a minor bug in
the test script).

  [1/5]: t5305: move cleanup into test block
  [2/5]: t5305: drop "dry-run" of unpack-objects
  [3/5]: t5305: use "git -C"
  [4/5]: t5305: simplify packname handling
  [5/5]: pack-objects: walk tag chains for --include-tag

-Peff

^ permalink raw reply

* [PATCH 1/5] t5305: move cleanup into test block
From: Jeff King @ 2016-09-05 21:52 UTC (permalink / raw)
  To: git
In-Reply-To: <20160905215141.b6unqtjqko7775is@sigill.intra.peff.net>

We usually try to avoid doing any significant actions
outside of test blocks. Although "rm -rf" is unlikely to
either fail or to generate output, moving these to the
point of use makes it more clear that they are part of the
overall setup of "clone.git".

Signed-off-by: Jeff King <peff@peff.net>
---
 t/t5305-include-tag.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index f314ad5..6018404 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -25,7 +25,6 @@ test_expect_success setup '
 	} >obj-list
 '
 
-rm -rf clone.git
 test_expect_success 'pack without --include-tag' '
 	packname_1=$(git pack-objects \
 		--window=0 \
@@ -33,6 +32,7 @@ test_expect_success 'pack without --include-tag' '
 '
 
 test_expect_success 'unpack objects' '
+	rm -rf clone.git &&
 	(
 		GIT_DIR=clone.git &&
 		export GIT_DIR &&
@@ -51,7 +51,6 @@ test_expect_success 'check unpacked result (have commit, no tag)' '
 	test_cmp list.expect list.actual
 '
 
-rm -rf clone.git
 test_expect_success 'pack with --include-tag' '
 	packname_1=$(git pack-objects \
 		--window=0 \
@@ -60,6 +59,7 @@ test_expect_success 'pack with --include-tag' '
 '
 
 test_expect_success 'unpack objects' '
+	rm -rf clone.git &&
 	(
 		GIT_DIR=clone.git &&
 		export GIT_DIR &&
-- 
2.10.0.rc2.154.gb4a4b8b


^ permalink raw reply related

* [PATCH 2/5] t5305: drop "dry-run" of unpack-objects
From: Jeff King @ 2016-09-05 21:52 UTC (permalink / raw)
  To: git
In-Reply-To: <20160905215141.b6unqtjqko7775is@sigill.intra.peff.net>

For each test we do a dry-run of unpack-objects, followed by
a real run, followed by confirming that it contained the
objects we expected. The dry-run is telling us nothing, as
any errors it encounters would be found in the real run.

Signed-off-by: Jeff King <peff@peff.net>
---
 t/t5305-include-tag.sh | 2 --
 1 file changed, 2 deletions(-)

diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index 6018404..787fc83 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -37,7 +37,6 @@ test_expect_success 'unpack objects' '
 		GIT_DIR=clone.git &&
 		export GIT_DIR &&
 		git init &&
-		git unpack-objects -n <test-1-${packname_1}.pack &&
 		git unpack-objects <test-1-${packname_1}.pack
 	)
 '
@@ -64,7 +63,6 @@ test_expect_success 'unpack objects' '
 		GIT_DIR=clone.git &&
 		export GIT_DIR &&
 		git init &&
-		git unpack-objects -n <test-2-${packname_1}.pack &&
 		git unpack-objects <test-2-${packname_1}.pack
 	)
 '
-- 
2.10.0.rc2.154.gb4a4b8b


^ permalink raw reply related

* [PATCH 3/5] t5305: use "git -C"
From: Jeff King @ 2016-09-05 21:52 UTC (permalink / raw)
  To: git
In-Reply-To: <20160905215141.b6unqtjqko7775is@sigill.intra.peff.net>

This test unpacks objects into a separate repository, and
accesses it by setting GIT_DIR in a subshell. We can do the
same thing these days by using "git init <repo>" and "git
-C". In most cases this is shorter, though when there are
multiple commands, we may end up repeating the "-C".

However, this repetition can actually be a good thing. This
patch also fixes a bug introduced by 512477b (tests: use
"env" to run commands with temporary env-var settings,
2014-03-18). That commit essentially converted:

   (GIT_DIR=...; export GIT_DIR
    cmd1 &&
    cmd2)

into:

   (GIT_DIR=... cmd1 &&
    cmd2)

which obviously loses the GIT_DIR setting for cmd2 (we never
noticed the bug because it simply runs "cmd2" in the parent
repo, which means we were simply failing to test anything
interesting). By using "git -C" rather than a subshell, it
becomes quite obvious where each command is supposed to be
running.

Signed-off-by: Jeff King <peff@peff.net>
---
 t/t5305-include-tag.sh | 28 +++++++---------------------
 1 file changed, 7 insertions(+), 21 deletions(-)

diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index 787fc83..089a3e9 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -33,20 +33,14 @@ test_expect_success 'pack without --include-tag' '
 
 test_expect_success 'unpack objects' '
 	rm -rf clone.git &&
-	(
-		GIT_DIR=clone.git &&
-		export GIT_DIR &&
-		git init &&
-		git unpack-objects <test-1-${packname_1}.pack
-	)
+	git init clone.git &&
+	git -C clone.git unpack-objects <test-1-${packname_1}.pack
 '
 
 test_expect_success 'check unpacked result (have commit, no tag)' '
 	git rev-list --objects $commit >list.expect &&
-	(
-		test_must_fail env GIT_DIR=clone.git git cat-file -e $tag &&
-		git rev-list --objects $commit
-	) >list.actual &&
+	test_must_fail git -C clone.git cat-file -e $tag &&
+	git -C clone.git rev-list --objects $commit >list.actual &&
 	test_cmp list.expect list.actual
 '
 
@@ -59,21 +53,13 @@ test_expect_success 'pack with --include-tag' '
 
 test_expect_success 'unpack objects' '
 	rm -rf clone.git &&
-	(
-		GIT_DIR=clone.git &&
-		export GIT_DIR &&
-		git init &&
-		git unpack-objects <test-2-${packname_1}.pack
-	)
+	git init clone.git &&
+	git -C clone.git unpack-objects <test-2-${packname_1}.pack
 '
 
 test_expect_success 'check unpacked result (have commit, have tag)' '
 	git rev-list --objects mytag >list.expect &&
-	(
-		GIT_DIR=clone.git &&
-		export GIT_DIR &&
-		git rev-list --objects $tag
-	) >list.actual &&
+	git -C clone.git rev-list --objects $tag >list.actual &&
 	test_cmp list.expect list.actual
 '
 
-- 
2.10.0.rc2.154.gb4a4b8b


^ permalink raw reply related

* [PATCH 4/5] t5305: simplify packname handling
From: Jeff King @ 2016-09-05 21:52 UTC (permalink / raw)
  To: git
In-Reply-To: <20160905215141.b6unqtjqko7775is@sigill.intra.peff.net>

We generate a series of packfiles test-1-$pack,
test-2-$pack, with different properties and then examine
them. However we always store the packname generated by
pack-objects in the variable packname_1. This probably was
meant to be packname_2 in the second test, but it turns out
that it doesn't matter: once we are done with the first
pack, we can just keep using the same $packname variable.

So let's drop the confusing "_1" parameter. At the same
time, let's give test-1 and test-2 more descriptive names,
which can help keep them straight (note that we _could_
likewise overwrite the packfiles in each test, but by using
separate filenames, we are sure that test 2 does not
accidentally use the packfile from test 1).

Signed-off-by: Jeff King <peff@peff.net>
---
 t/t5305-include-tag.sh | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index 089a3e9..e3c6c62 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -26,15 +26,15 @@ test_expect_success setup '
 '
 
 test_expect_success 'pack without --include-tag' '
-	packname_1=$(git pack-objects \
+	packname=$(git pack-objects \
 		--window=0 \
-		test-1 <obj-list)
+		test-no-include <obj-list)
 '
 
 test_expect_success 'unpack objects' '
 	rm -rf clone.git &&
 	git init clone.git &&
-	git -C clone.git unpack-objects <test-1-${packname_1}.pack
+	git -C clone.git unpack-objects <test-no-include-${packname}.pack
 '
 
 test_expect_success 'check unpacked result (have commit, no tag)' '
@@ -45,16 +45,16 @@ test_expect_success 'check unpacked result (have commit, no tag)' '
 '
 
 test_expect_success 'pack with --include-tag' '
-	packname_1=$(git pack-objects \
+	packname=$(git pack-objects \
 		--window=0 \
 		--include-tag \
-		test-2 <obj-list)
+		test-include <obj-list)
 '
 
 test_expect_success 'unpack objects' '
 	rm -rf clone.git &&
 	git init clone.git &&
-	git -C clone.git unpack-objects <test-2-${packname_1}.pack
+	git -C clone.git unpack-objects <test-include-${packname}.pack
 '
 
 test_expect_success 'check unpacked result (have commit, have tag)' '
-- 
2.10.0.rc2.154.gb4a4b8b


^ permalink raw reply related

* [PATCH 5/5] pack-objects: walk tag chains for --include-tag
From: Jeff King @ 2016-09-05 21:52 UTC (permalink / raw)
  To: git
In-Reply-To: <20160905215141.b6unqtjqko7775is@sigill.intra.peff.net>

When pack-objects is given --include-tag, it peels each tag
ref down to a non-tag object, and if that non-tag object is
going to be packed, we include the tag, too. But what
happens if we have a chain of tags (e.g., tag "A" points to
tag "B", which points to commit "C")?

We'll peel down to "C" and realize that we want to include
tag "A", but we do not ever consider tag "B", leading to a
broken pack (assuming "B" was not otherwise selected).
Instead, we have to walk the whole chain, adding any tags we
find to the pack.

Interestingly, it doesn't seem possible to trigger this
problem with "git fetch", but you can with "git clone
--single-branch". The reason is that we generate the correct
pack when the client explicitly asks for "A" (because we do
a real reachability analysis there), and "fetch" is more
willing to do so. There are basically two cases:

  1. If "C" is already a ref tip, then the client can deduce
     that it needs "A" itself (via find_non_local_tags), and
     will ask for it explicitly rather than relying on the
     include-tag capability. Everything works.

  2. If "C" is not already a ref tip, then we hope for
     include-tag to send us the correct tag. But it doesn't;
     it generates a broken pack. However, the next step is
     to do a follow-up run of find_non_local_tags(),
     followed by fetch_refs() to backfill any tags we
     learned about.

     In the normal case, fetch_refs() calls quickfetch(),
     which does a connectivity check and sees we have no
     new objects to fetch. We just write the refs.

     But for the broken-pack case, the connectivity check
     fails, and quickfetch will follow-up with the remote,
     asking explicitly for each of the ref tips. This picks
     up the missing object in a new pack.

For a regular "git clone", we are similarly OK, because we
explicitly request all of the tag refs, and get a correct
pack. But with "--single-branch", we kick in tag
auto-following via "include-tag", but do _not_ do a
follow-up backfill. We just take whatever the server sent us
via include-tag and write out tag refs for any tag objects
we were sent. So prior to c6807a4 (clone: open a shortcut
for connectivity check, 2013-05-26), we actually claimed the
clone was a success, but the result was silently
corrupted!  Since c6807a4, index-pack's connectivity
check catches this case, and we correctly complain.

The included test directly checks that pack-objects does not
generate a broken pack, but also confirms that "clone
--single-branch" does not hit the bug.

Note that tag chains introduce another interesting question:
if we are packing the tag "B" but not the commit "C", should
"A" be included?

Both before and after this patch, we do not include "A",
because the initial peel_ref() check only knows about the
bottom-most level, "C". To realize that "B" is involved at
all, we would have to switch to an incremental peel, in
which we examine each tagged object, asking if it is being
packed (and including the outer tag if so).

But that runs contrary to the optimizations in peel_ref(),
which avoid accessing the objects at all, in favor of using
the value we pull from packed-refs. It's OK to walk the
whole chain once we know we're going to include the tag (we
have to access it anyway, so the effort is proportional to
the pack we're generating). But for the initial selection,
we have to look at every ref. If we're only packing a few
objects, we'd still have to parse every single referenced
tag object just to confirm that it isn't part of a tag
chain.

This could be addressed if packed-refs stored the complete
tag chain for each peeled ref (in most cases, this would be
the same cost as now, as each "chain" is only a single
link). But given the size of that project, it's out of scope
for this fix (and probably nobody cares enough anyway, as
it's such an obscure situation). This commit limits itself
to just avoiding the creation of a broken pack.

Signed-off-by: Jeff King <peff@peff.net>
---
 builtin/pack-objects.c | 31 +++++++++++++++++++++++++++++-
 t/t5305-include-tag.sh | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 4a63398..0954375 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2123,6 +2123,35 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
 #define ll_find_deltas(l, s, w, d, p)	find_deltas(l, &s, w, d, p)
 #endif
 
+static void add_tag_chain(const struct object_id *oid)
+{
+	struct tag *tag;
+
+	/*
+	 * We catch duplicates already in add_object_entry(), but we'd
+	 * prefer to do this extra check to avoid having to parse the
+	 * tag at all if we already know that it's being packed (e.g., if
+	 * it was included via bitmaps, we would not have parsed it
+	 * previously).
+	 */
+	if (packlist_find(&to_pack, oid->hash, NULL))
+		return;
+
+	tag = lookup_tag(oid->hash);
+	while (1) {
+		if (!tag || parse_tag(tag) || !tag->tagged)
+			die("unable to pack objects reachable from tag %s",
+			    oid_to_hex(oid));
+
+		add_object_entry(tag->object.oid.hash, OBJ_TAG, NULL, 0);
+
+		if (tag->tagged->type != OBJ_TAG)
+			return;
+
+		tag = (struct tag *)tag->tagged;
+	}
+}
+
 static int add_ref_tag(const char *path, const struct object_id *oid, int flag, void *cb_data)
 {
 	struct object_id peeled;
@@ -2130,7 +2159,7 @@ static int add_ref_tag(const char *path, const struct object_id *oid, int flag,
 	if (starts_with(path, "refs/tags/") && /* is a tag? */
 	    !peel_ref(path, peeled.hash)    && /* peelable? */
 	    packlist_find(&to_pack, peeled.hash, NULL))      /* object packed? */
-		add_object_entry(oid->hash, OBJ_TAG, NULL, 0);
+		add_tag_chain(oid);
 	return 0;
 }
 
diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index e3c6c62..a5eca21 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -63,4 +63,56 @@ test_expect_success 'check unpacked result (have commit, have tag)' '
 	test_cmp list.expect list.actual
 '
 
+# A tag of a tag, where the "inner" tag is not otherwise
+# reachable, and a full peel points to a commit reachable from HEAD.
+test_expect_success 'create hidden inner tag' '
+	test_commit commit &&
+	git tag -m inner inner HEAD &&
+	git tag -m outer outer inner &&
+	git tag -d inner
+'
+
+test_expect_success 'pack explicit outer tag' '
+	packname=$(
+		{
+			echo HEAD &&
+			echo outer
+		} |
+		git pack-objects --revs test-hidden-explicit
+	)
+'
+
+test_expect_success 'unpack objects' '
+	rm -rf clone.git &&
+	git init clone.git &&
+	git -C clone.git unpack-objects <test-hidden-explicit-${packname}.pack
+'
+
+test_expect_success 'check unpacked result (have all objects)' '
+	git -C clone.git rev-list --objects $(git rev-parse outer HEAD)
+'
+
+test_expect_success 'pack implied outer tag' '
+	packname=$(
+		echo HEAD |
+		git pack-objects --revs --include-tag test-hidden-implied
+	)
+'
+
+test_expect_success 'unpack objects' '
+	rm -rf clone.git &&
+	git init clone.git &&
+	git -C clone.git unpack-objects <test-hidden-implied-${packname}.pack
+'
+
+test_expect_success 'check unpacked result (have all objects)' '
+	git -C clone.git rev-list --objects $(git rev-parse outer HEAD)
+'
+
+test_expect_success 'single-branch clone can transfer tag' '
+	rm -rf clone.git &&
+	git clone --no-local --single-branch -b master . clone.git &&
+	git -C clone.git fsck
+'
+
 test_done
-- 
2.10.0.rc2.154.gb4a4b8b

^ permalink raw reply related

* Re: [PATCH 0/5] handle tag recursion in pack-objects --include-tag
From: Jeff King @ 2016-09-05 21:54 UTC (permalink / raw)
  To: git
In-Reply-To: <20160905215141.b6unqtjqko7775is@sigill.intra.peff.net>

On Mon, Sep 05, 2016 at 05:51:41PM -0400, Jeff King wrote:

> If you have a tag of a tag of a commit, and the middle tag isn't
> otherwise reachable, then "pack-objects --include-tag" will not include
> the middle tag, and certain invocations of "clone" will fail. See the
> final patch below for the gory details.
> 
> The first five patches are just test cleanup and modernization in
> preparation (though note that the 3rd one actually fixes a minor bug in
> the test script).
> 
>   [1/5]: t5305: move cleanup into test block
>   [2/5]: t5305: drop "dry-run" of unpack-objects
>   [3/5]: t5305: use "git -C"
>   [4/5]: t5305: simplify packname handling
>   [5/5]: pack-objects: walk tag chains for --include-tag

BTW, this is not a new regression; the problem dates back to the origin
of the "include-tag" feature. So there is no urgency to the fix, as it
has been with us for almost a decade. I built it on master, but it
should apply cleanly to maint.

-Peff

^ permalink raw reply

* Re: [PATCH] stash: allow ref of a stash by index
From: Øystein Walle @ 2016-09-05 21:58 UTC (permalink / raw)
  To: Git
In-Reply-To: <CAFaJEqu-JUcwLjrQBk_huSa3DZfCf8O4eAZ=UgcXHzN=CLgtpw@mail.gmail.com>

Pasting text into Gmail's web interface is not conducive to sending tabs
through the intertubes. But you get the idea..

Øsse

^ permalink raw reply

* Re: [PATCH 5/5] pack-objects: walk tag chains for --include-tag
From: Jeff King @ 2016-09-05 21:59 UTC (permalink / raw)
  To: git
In-Reply-To: <20160905215226.m6vv2tk5pe2qt4ui@sigill.intra.peff.net>

On Mon, Sep 05, 2016 at 05:52:26PM -0400, Jeff King wrote:

> When pack-objects is given --include-tag, it peels each tag
> ref down to a non-tag object, and if that non-tag object is
> going to be packed, we include the tag, too. But what
> happens if we have a chain of tags (e.g., tag "A" points to
> tag "B", which points to commit "C")?
> 
> We'll peel down to "C" and realize that we want to include
> tag "A", but we do not ever consider tag "B", leading to a
> broken pack (assuming "B" was not otherwise selected).
> Instead, we have to walk the whole chain, adding any tags we
> find to the pack.

So technically one might argue that this pack isn't "broken", in that it
_is_ a valid pack. It's just that it doesn't contain what the user was
asking for.

As explained further in the commit message, "fetch" is robust to this,
because it does a real connectivity check and follow-on fetch before
writing anything it thinks it got via include-tag. So perhaps one could
argue that pack-objects is correct; include-tag is best-effort, and it
is the client's job to make sure it has everything it needs. And that
would mean the bug is in git-clone, which should be doing the
connectivity check and follow-on fetch.

I dunno. This seems like the most elegant place to fix it, though it
does mean that pack-objects will go to some slight extra work when
auto-packing a tag (it has to parse the tag to find out whether it's a
chain). I'm doubt it matters much in practice.

-Peff

^ permalink raw reply

* Re: [PATCH v1 1/2] sha1_file: open window into packfiles with CLOEXEC
From: Eric Wong @ 2016-09-05 22:27 UTC (permalink / raw)
  To: larsxschneider; +Cc: git, gitster, tboegi, Johannes.Schindelin
In-Reply-To: <20160905211111.72956-2-larsxschneider@gmail.com>

larsxschneider@gmail.com wrote:
> All processes that the Git main process spawns inherit the open file
> descriptors of the main process. These leaked file descriptors can
> cause problems.


> -int git_open_noatime(const char *name)
> +int git_open_noatime_cloexec(const char *name)
>  {
> -	static int sha1_file_open_flag = O_NOATIME;
> +	static int sha1_file_open_flag = O_NOATIME | O_CLOEXEC;
>  
>  	for (;;) {
>  		int fd;

If there's real problems being caused by lack of cloexec
today, I think the F_SETFD fallback I proposed in
https://public-inbox.org/git/20160818173555.GA29253@starla/
will be necessary.

I question the need for the "_cloexec" suffixing in the
function name since the old function is going away entirely.

I prefer all FD-creating functions set cloexec by default
for FD > 2 to avoid inadvertantly leaking FDs.  So we
ought to use pipe2, accept4, socket(..., SOCK_CLOEXEC), etc...
and fallback to the racy+slower F_SETFD when not available.


Fwiw, Perl has been setting cloexec on FDs above $^F
(2, $SYSTEM_FD_MAX) for decades, and Ruby started
doing it a few years ago, too.

^ permalink raw reply

* 2.10.0: multiple versionsort.prereleasesuffix buggy?
From: Leho Kraav (Conversion Ready) @ 2016-09-05 22:42 UTC (permalink / raw)
  To: git

Hi all


Here's the testing tree https://github.com/woothemes/woocommerce

.git/config has:

[versionsort] 
 

     prereleasesuffix = -beta
     prereleasesuffix = -RC

$ git tag -l --sort=version:refname
...
2.5.0-RC1
2.5.0-RC2
2.5.0-RC3
2.5.0-beta-1
2.5.0-beta-2
2.5.0-beta-3
2.5.0
2.5.1
2.5.2
2.5.3
2.5.4
2.5.5
2.6.0-RC1
2.6.0-RC2
2.6.0-beta-1
2.6.0-beta-2
2.6.0-beta-3
2.6.0-beta-4
2.6.0
2.6.1
2.6.2
2.6.3
2.6.4

Per documentation, I'm supposed to see something like
...
2.5.0-beta-1
2.5.0-beta-2
2.5.0-beta-3
2.5.0-RC1
2.5.0-RC2
2.5.0-RC3
2.5.0
...


No matter what I do in `.git/config`, RC goes up front. What's going on?

(Yes, this project's tag capitalization is messed up.)

^ 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