{"thread":{"id":"42656","subject":"[PATCH v2 0/8] object_id part 4","startedAt":"2016-06-18T22:14:19Z","lastAt":"2016-06-24T15:28:01Z","messageCount":20,"participants":["brian m. carlson","Johannes Sixt","Jeff King","Johannes Schindelin","Junio C Hamano"],"isPatch":true,"patchVersion":2,"patchTotal":8},"messages":[{"id":"289584","messageId":"20160618221407.1046188-1-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":null,"subject":"[PATCH v2 0/8] object_id part 4","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:13:59Z","receivedAt":"2016-06-18T22:14:19Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"This series is part 4 in a series of conversions to replace instances of\nunsigned char [20] with struct object_id.  Most of this series touches\nthe merge-recursive code.\n\nNew in this series is the use of Coccinelle (http://coccinelle.lip6.fr/)\nsemantic patches.  These semantic patches can make automatic\ntransformations to C source code for cleanup or refactoring reasons.\n\nThis series introduces a set of transforms for the struct object_id\ntransition, cleans up some existing code with them, and applies a small\nnumber of semantic patches to transform parts of the merge-recursive\ncode.  Some manual refactoring work follows.\n\nNote that in the patches created with the semantic patches, the only manual\nchange was the definition of the struct member.  Opinions on whether this is a\nviable technique for further work to ease both the creation and review of\npatches are of course welcomed.\n\nThe testsuite continues to pass at each step, and this series rebases\ncleanly on both pu and next.\n\nI moved the Coccinelle transforms to contrib/examples/coccinelle, but if\nit's decided that the Coccinelle transforms simply don't belong in the\nrepository, it's fine to simply drop the first patch (and maybe fix up\nthe commit messages).  I can create a GitHub Gist and let reviewers\nrefer to that at their convenience.\n\nChanges from v1:\n* Move the object ID transformations to contrib/examples/coccinelle.\n* Add a README to that folder explaining what they are.\n* Adjust the Coccinelle patches to transform plain structs before\n  pointers to structs to avoid misconversions.  This addresses the issue\n  that Peff caught originally.\n\nbrian m. carlson (8):\n  Add basic Coccinelle transforms.\n  Apply object_id Coccinelle transformations.\n  Convert struct diff_filespec to struct object_id\n  Rename struct diff_filespec's sha1_valid member.\n  merge-recursive: convert struct stage_data to use object_id\n  merge-recursive: convert struct merge_file_info to object_id\n  merge-recursive: convert leaf functions to use struct object_id\n  merge-recursive: convert merge_recursive_generic to object_id\n\n bisect.c                                    |   2 +-\n builtin/blame.c                             |   6 +-\n builtin/fast-export.c                       |  10 +-\n builtin/merge-recursive.c                   |  20 +-\n builtin/merge.c                             |  13 +-\n builtin/reset.c                             |   4 +-\n combine-diff.c                              |  14 +-\n contrib/examples/coccinelle/README          |   2 +\n contrib/examples/coccinelle/object_id.cocci |  83 ++++++++\n diff.c                                      |  95 +++++----\n diffcore-break.c                            |   4 +-\n diffcore-rename.c                           |  16 +-\n diffcore.h                                  |   4 +-\n line-log.c                                  |  12 +-\n merge-recursive.c                           | 310 ++++++++++++++--------------\n merge-recursive.h                           |   6 +-\n notes-merge.c                               |  42 ++--\n refs/files-backend.c                        |   4 +-\n submodule.c                                 |   4 +-\n wt-status.c                                 |   3 +-\n 20 files changed, 378 insertions(+), 276 deletions(-)\n create mode 100644 contrib/examples/coccinelle/README\n create mode 100644 contrib/examples/coccinelle/object_id.cocci\n"},{"id":"289585","messageId":"20160618221407.1046188-7-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"[PATCH v2 6/8] merge-recursive: convert struct merge_file_info to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:14:05Z","receivedAt":"2016-06-18T22:14:23Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert struct merge_file_info to use struct object_id.  The following\nCoccinelle semantic patch was used to implement this, followed by the\ntransformations in object_id.cocci:\n\n@@\nstruct merge_file_info o;\n@@\n- o.sha\n+ o.oid.hash\n\n@@\nstruct merge_file_info *p;\n@@\n- p->sha\n+ p->oid.hash\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n merge-recursive.c | 39 ++++++++++++++++++++-------------------\n 1 file changed, 20 insertions(+), 19 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex a07050cd..bc455491 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -819,7 +819,7 @@ static void update_file(struct merge_options *o,\n /* Low level file merging, update and removal */\n \n struct merge_file_info {\n-\tunsigned char sha[20];\n+\tstruct object_id oid;\n \tunsigned mode;\n \tunsigned clean:1,\n \t\t merge:1;\n@@ -902,10 +902,10 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\tresult.clean = 0;\n \t\tif (S_ISREG(a->mode)) {\n \t\t\tresult.mode = a->mode;\n-\t\t\thashcpy(result.sha, a->oid.hash);\n+\t\t\toidcpy(&result.oid, &a->oid);\n \t\t} else {\n \t\t\tresult.mode = b->mode;\n-\t\t\thashcpy(result.sha, b->oid.hash);\n+\t\t\toidcpy(&result.oid, &b->oid);\n \t\t}\n \t} else {\n \t\tif (!sha_eq(a->oid.hash, one->oid.hash) && !sha_eq(b->oid.hash, one->oid.hash))\n@@ -925,9 +925,9 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\t}\n \n \t\tif (sha_eq(a->oid.hash, b->oid.hash) || sha_eq(a->oid.hash, one->oid.hash))\n-\t\t\thashcpy(result.sha, b->oid.hash);\n+\t\t\toidcpy(&result.oid, &b->oid);\n \t\telse if (sha_eq(b->oid.hash, one->oid.hash))\n-\t\t\thashcpy(result.sha, a->oid.hash);\n+\t\t\toidcpy(&result.oid, &a->oid);\n \t\telse if (S_ISREG(a->mode)) {\n \t\t\tmmbuffer_t result_buf;\n \t\t\tint merge_status;\n@@ -939,21 +939,21 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\t\t\tdie(_(\"Failed to execute internal merge\"));\n \n \t\t\tif (write_sha1_file(result_buf.ptr, result_buf.size,\n-\t\t\t\t\t    blob_type, result.sha))\n+\t\t\t\t\t    blob_type, result.oid.hash))\n \t\t\t\tdie(_(\"Unable to add %s to database\"),\n \t\t\t\t    a->path);\n \n \t\t\tfree(result_buf.ptr);\n \t\t\tresult.clean = (merge_status == 0);\n \t\t} else if (S_ISGITLINK(a->mode)) {\n-\t\t\tresult.clean = merge_submodule(result.sha,\n+\t\t\tresult.clean = merge_submodule(result.oid.hash,\n \t\t\t\t\t\t       one->path,\n \t\t\t\t\t\t       one->oid.hash,\n \t\t\t\t\t\t       a->oid.hash,\n \t\t\t\t\t\t       b->oid.hash,\n \t\t\t\t\t\t       !o->call_depth);\n \t\t} else if (S_ISLNK(a->mode)) {\n-\t\t\thashcpy(result.sha, a->oid.hash);\n+\t\t\toidcpy(&result.oid, &a->oid);\n \n \t\t\tif (!sha_eq(a->oid.hash, b->oid.hash))\n \t\t\t\tresult.clean = 0;\n@@ -1192,7 +1192,7 @@ static void conflict_rename_rename_1to2(struct merge_options *o,\n \t\t * pathname and then either rename the add-source file to that\n \t\t * unique path, or use that unique path instead of src here.\n \t\t */\n-\t\tupdate_file(o, 0, mfi.sha, mfi.mode, one->path);\n+\t\tupdate_file(o, 0, mfi.oid.hash, mfi.mode, one->path);\n \n \t\t/*\n \t\t * Above, we put the merged content at the merge-base's\n@@ -1255,16 +1255,16 @@ static void conflict_rename_rename_2to1(struct merge_options *o,\n \t\t * again later for the non-recursive merge.\n \t\t */\n \t\tremove_file(o, 0, path, 0);\n-\t\tupdate_file(o, 0, mfi_c1.sha, mfi_c1.mode, a->path);\n-\t\tupdate_file(o, 0, mfi_c2.sha, mfi_c2.mode, b->path);\n+\t\tupdate_file(o, 0, mfi_c1.oid.hash, mfi_c1.mode, a->path);\n+\t\tupdate_file(o, 0, mfi_c2.oid.hash, mfi_c2.mode, b->path);\n \t} else {\n \t\tchar *new_path1 = unique_path(o, path, ci->branch1);\n \t\tchar *new_path2 = unique_path(o, path, ci->branch2);\n \t\toutput(o, 1, _(\"Renaming %s to %s and %s to %s instead\"),\n \t\t       a->path, new_path1, b->path, new_path2);\n \t\tremove_file(o, 0, path, 0);\n-\t\tupdate_file(o, 0, mfi_c1.sha, mfi_c1.mode, new_path1);\n-\t\tupdate_file(o, 0, mfi_c2.sha, mfi_c2.mode, new_path2);\n+\t\tupdate_file(o, 0, mfi_c1.oid.hash, mfi_c1.mode, new_path1);\n+\t\tupdate_file(o, 0, mfi_c2.oid.hash, mfi_c2.mode, new_path2);\n \t\tfree(new_path2);\n \t\tfree(new_path1);\n \t}\n@@ -1474,7 +1474,8 @@ static int process_renames(struct merge_options *o,\n \t\t\t\t\t\t\t dst_other.mode,\n \t\t\t\t\t\t\t branch1, branch2);\n \t\t\t\t\toutput(o, 1, _(\"Adding merged %s\"), ren1_dst);\n-\t\t\t\t\tupdate_file(o, 0, mfi.sha, mfi.mode, ren1_dst);\n+\t\t\t\t\tupdate_file(o, 0, mfi.oid.hash,\n+\t\t\t\t\t\t    mfi.mode, ren1_dst);\n \t\t\t\t\ttry_merge = 0;\n \t\t\t\t} else {\n \t\t\t\t\tchar *new_path = unique_path(o, ren1_dst, branch2);\n@@ -1634,7 +1635,7 @@ static int merge_content(struct merge_options *o,\n \t\t\t\t\t o->branch2, path2);\n \n \tif (mfi.clean && !df_conflict_remains &&\n-\t    sha_eq(mfi.sha, a_sha) && mfi.mode == a_mode) {\n+\t    sha_eq(mfi.oid.hash, a_sha) && mfi.mode == a_mode) {\n \t\tint path_renamed_outside_HEAD;\n \t\toutput(o, 3, _(\"Skipped %s (merged same as existing)\"), path);\n \t\t/*\n@@ -1645,7 +1646,7 @@ static int merge_content(struct merge_options *o,\n \t\t */\n \t\tpath_renamed_outside_HEAD = !path2 || !strcmp(path, path2);\n \t\tif (!path_renamed_outside_HEAD) {\n-\t\t\tadd_cacheinfo(mfi.mode, mfi.sha, path,\n+\t\t\tadd_cacheinfo(mfi.mode, mfi.oid.hash, path,\n \t\t\t\t      0, (!o->call_depth), 0);\n \t\t\treturn mfi.clean;\n \t\t}\n@@ -1671,7 +1672,7 @@ static int merge_content(struct merge_options *o,\n \t\t\telse {\n \t\t\t\tint file_from_stage2 = was_tracked(path);\n \t\t\t\tstruct diff_filespec merged;\n-\t\t\t\thashcpy(merged.oid.hash, mfi.sha);\n+\t\t\t\toidcpy(&merged.oid, &mfi.oid);\n \t\t\t\tmerged.mode = mfi.mode;\n \n \t\t\t\tupdate_stages(path, NULL,\n@@ -1682,11 +1683,11 @@ static int merge_content(struct merge_options *o,\n \t\t}\n \t\tnew_path = unique_path(o, path, rename_conflict_info->branch1);\n \t\toutput(o, 1, _(\"Adding as %s instead\"), new_path);\n-\t\tupdate_file(o, 0, mfi.sha, mfi.mode, new_path);\n+\t\tupdate_file(o, 0, mfi.oid.hash, mfi.mode, new_path);\n \t\tfree(new_path);\n \t\tmfi.clean = 0;\n \t} else {\n-\t\tupdate_file(o, mfi.clean, mfi.sha, mfi.mode, path);\n+\t\tupdate_file(o, mfi.clean, mfi.oid.hash, mfi.mode, path);\n \t}\n \treturn mfi.clean;\n \n"},{"id":"289586","messageId":"20160618221407.1046188-5-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"[PATCH v2 4/8] Rename struct diff_filespec's sha1_valid member.","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:14:03Z","receivedAt":"2016-06-18T22:14:26Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Now that this struct's sha1 member is called \"oid\", update the comment\nand the sha1_valid member to be called \"oid_valid\" instead.  The\nfollowing Coccinelle semantic patch was used to implement this, followed\nby the transformations in object_id.cocci:\n\n@@\nstruct diff_filespec o;\n@@\n- o.sha1_valid\n+ o.oid_valid\n\n@@\nstruct diff_filespec *p;\n@@\n- p->sha1_valid\n+ p->oid_valid\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n combine-diff.c    |  4 ++--\n diff.c            | 28 ++++++++++++++--------------\n diffcore-break.c  |  2 +-\n diffcore-rename.c |  4 ++--\n diffcore.h        |  2 +-\n line-log.c        | 10 +++++-----\n 6 files changed, 25 insertions(+), 25 deletions(-)\n\ndiff --git a/combine-diff.c b/combine-diff.c\nindex 3537209c..5940dc87 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -1269,7 +1269,7 @@ static struct diff_filepair *combined_pair(struct combine_diff_path *p,\n \t\tpair->one[i].path = p->path;\n \t\tpair->one[i].mode = p->parent[i].mode;\n \t\toidcpy(&pair->one[i].oid, &p->parent[i].oid);\n-\t\tpair->one[i].sha1_valid = !is_null_oid(&p->parent[i].oid);\n+\t\tpair->one[i].oid_valid = !is_null_oid(&p->parent[i].oid);\n \t\tpair->one[i].has_more_entries = 1;\n \t}\n \tpair->one[num_parent - 1].has_more_entries = 0;\n@@ -1277,7 +1277,7 @@ static struct diff_filepair *combined_pair(struct combine_diff_path *p,\n \tpair->two->path = p->path;\n \tpair->two->mode = p->mode;\n \toidcpy(&pair->two->oid, &p->oid);\n-\tpair->two->sha1_valid = !is_null_oid(&p->oid);\n+\tpair->two->oid_valid = !is_null_oid(&p->oid);\n \treturn pair;\n }\n \ndiff --git a/diff.c b/diff.c\nindex 5a6d8654..a7a553b8 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1933,7 +1933,7 @@ static void show_dirstat(struct diff_options *options)\n \n \t\tname = p->two->path ? p->two->path : p->one->path;\n \n-\t\tif (p->one->sha1_valid && p->two->sha1_valid)\n+\t\tif (p->one->oid_valid && p->two->oid_valid)\n \t\t\tcontent_changed = oidcmp(&p->one->oid, &p->two->oid);\n \t\telse\n \t\t\tcontent_changed = 1;\n@@ -2640,7 +2640,7 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,\n \tif (mode) {\n \t\tspec->mode = canon_mode(mode);\n \t\thashcpy(spec->oid.hash, sha1);\n-\t\tspec->sha1_valid = sha1_valid;\n+\t\tspec->oid_valid = sha1_valid;\n \t}\n }\n \n@@ -2766,7 +2766,7 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)\n \tif (S_ISGITLINK(s->mode))\n \t\treturn diff_populate_gitlink(s, size_only);\n \n-\tif (!s->sha1_valid ||\n+\tif (!s->oid_valid ||\n \t    reuse_worktree_file(s->path, s->oid.hash, 0)) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n \t\tstruct stat st;\n@@ -2915,7 +2915,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n \t}\n \n \tif (!S_ISGITLINK(one->mode) &&\n-\t    (!one->sha1_valid ||\n+\t    (!one->oid_valid ||\n \t     reuse_worktree_file(name, one->oid.hash, 1))) {\n \t\tstruct stat st;\n \t\tif (lstat(name, &st) < 0) {\n@@ -2928,16 +2928,16 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n \t\t\tif (strbuf_readlink(&sb, name, st.st_size) < 0)\n \t\t\t\tdie_errno(\"readlink(%s)\", name);\n \t\t\tprep_temp_blob(name, temp, sb.buf, sb.len,\n-\t\t\t\t       (one->sha1_valid ?\n+\t\t\t\t       (one->oid_valid ?\n \t\t\t\t\tone->oid.hash : null_sha1),\n-\t\t\t\t       (one->sha1_valid ?\n+\t\t\t\t       (one->oid_valid ?\n \t\t\t\t\tone->mode : S_IFLNK));\n \t\t\tstrbuf_release(&sb);\n \t\t}\n \t\telse {\n \t\t\t/* we can borrow from the file in the work tree */\n \t\t\ttemp->name = name;\n-\t\t\tif (!one->sha1_valid)\n+\t\t\tif (!one->oid_valid)\n \t\t\t\tsha1_to_hex_r(temp->hex, null_sha1);\n \t\t\telse\n \t\t\t\tsha1_to_hex_r(temp->hex, one->oid.hash);\n@@ -3134,7 +3134,7 @@ static void run_diff_cmd(const char *pgm,\n static void diff_fill_sha1_info(struct diff_filespec *one)\n {\n \tif (DIFF_FILE_VALID(one)) {\n-\t\tif (!one->sha1_valid) {\n+\t\tif (!one->oid_valid) {\n \t\t\tstruct stat st;\n \t\t\tif (one->is_stdin) {\n \t\t\t\thashcpy(one->oid.hash, null_sha1);\n@@ -4172,11 +4172,11 @@ int diff_unmodified_pair(struct diff_filepair *p)\n \t/* both are valid and point at the same path.  that is, we are\n \t * dealing with a change.\n \t */\n-\tif (one->sha1_valid && two->sha1_valid &&\n+\tif (one->oid_valid && two->oid_valid &&\n \t    !oidcmp(&one->oid, &two->oid) &&\n \t    !one->dirty_submodule && !two->dirty_submodule)\n \t\treturn 1; /* no change */\n-\tif (!one->sha1_valid && !two->sha1_valid)\n+\tif (!one->oid_valid && !two->oid_valid)\n \t\treturn 1; /* both look at the same file on the filesystem. */\n \treturn 0;\n }\n@@ -4237,7 +4237,7 @@ void diff_debug_filespec(struct diff_filespec *s, int x, const char *one)\n \t\ts->path,\n \t\tDIFF_FILE_VALID(s) ? \"valid\" : \"invalid\",\n \t\ts->mode,\n-\t\ts->sha1_valid ? oid_to_hex(&s->oid) : \"\");\n+\t\ts->oid_valid ? oid_to_hex(&s->oid) : \"\");\n \tfprintf(stderr, \"queue[%d] %s size %lu\\n\",\n \t\tx, one ? one : \"\",\n \t\ts->size);\n@@ -4822,7 +4822,7 @@ static int diff_filespec_check_stat_unmatch(struct diff_filepair *p)\n \t */\n \tif (!DIFF_FILE_VALID(p->one) || /* (1) */\n \t    !DIFF_FILE_VALID(p->two) ||\n-\t    (p->one->sha1_valid && p->two->sha1_valid) ||\n+\t    (p->one->oid_valid && p->two->oid_valid) ||\n \t    (p->one->mode != p->two->mode) ||\n \t    diff_populate_filespec(p->one, CHECK_SIZE_ONLY) ||\n \t    diff_populate_filespec(p->two, CHECK_SIZE_ONLY) ||\n@@ -5118,7 +5118,7 @@ size_t fill_textconv(struct userdiff_driver *driver,\n \tif (!driver->textconv)\n \t\tdie(\"BUG: fill_textconv called with non-textconv driver\");\n \n-\tif (driver->textconv_cache && df->sha1_valid) {\n+\tif (driver->textconv_cache && df->oid_valid) {\n \t\t*outbuf = notes_cache_get(driver->textconv_cache,\n \t\t\t\t\t  df->oid.hash,\n \t\t\t\t\t  &size);\n@@ -5130,7 +5130,7 @@ size_t fill_textconv(struct userdiff_driver *driver,\n \tif (!*outbuf)\n \t\tdie(\"unable to read files to diff\");\n \n-\tif (driver->textconv_cache && df->sha1_valid) {\n+\tif (driver->textconv_cache && df->oid_valid) {\n \t\t/* ignore errors, as we might be in a readonly repository */\n \t\tnotes_cache_put(driver->textconv_cache, df->oid.hash, *outbuf,\n \t\t\t\tsize);\ndiff --git a/diffcore-break.c b/diffcore-break.c\nindex a3e79608..881a74f2 100644\n--- a/diffcore-break.c\n+++ b/diffcore-break.c\n@@ -57,7 +57,7 @@ static int should_break(struct diff_filespec *src,\n \t\treturn 1; /* even their types are different */\n \t}\n \n-\tif (src->sha1_valid && dst->sha1_valid &&\n+\tif (src->oid_valid && dst->oid_valid &&\n \t    !oidcmp(&src->oid, &dst->oid))\n \t\treturn 0; /* they are the same */\n \ndiff --git a/diffcore-rename.c b/diffcore-rename.c\nindex 22b239a4..58ac0a53 100644\n--- a/diffcore-rename.c\n+++ b/diffcore-rename.c\n@@ -60,7 +60,7 @@ static int add_rename_dst(struct diff_filespec *two)\n \t\tmemmove(rename_dst + first + 1, rename_dst + first,\n \t\t\t(rename_dst_nr - first - 1) * sizeof(*rename_dst));\n \trename_dst[first].two = alloc_filespec(two->path);\n-\tfill_filespec(rename_dst[first].two, two->oid.hash, two->sha1_valid,\n+\tfill_filespec(rename_dst[first].two, two->oid.hash, two->oid_valid,\n \t\t      two->mode);\n \trename_dst[first].pair = NULL;\n \treturn 0;\n@@ -261,7 +261,7 @@ struct file_similarity {\n \n static unsigned int hash_filespec(struct diff_filespec *filespec)\n {\n-\tif (!filespec->sha1_valid) {\n+\tif (!filespec->oid_valid) {\n \t\tif (diff_populate_filespec(filespec, 0))\n \t\t\treturn 0;\n \t\thash_sha1_file(filespec->data, filespec->size, \"blob\",\ndiff --git a/diffcore.h b/diffcore.h\nindex c40e5b6c..c11b8465 100644\n--- a/diffcore.h\n+++ b/diffcore.h\n@@ -33,7 +33,7 @@ struct diff_filespec {\n \tint count;               /* Reference count */\n \tint rename_used;         /* Count of rename users */\n \tunsigned short mode;\t /* file mode */\n-\tunsigned sha1_valid : 1; /* if true, use sha1 and trust mode;\n+\tunsigned oid_valid : 1;  /* if true, use oid and trust mode;\n \t\t\t\t  * if false, use the name and read from\n \t\t\t\t  * the filesystem.\n \t\t\t\t  */\ndiff --git a/line-log.c b/line-log.c\nindex 02938639..93407baa 100644\n--- a/line-log.c\n+++ b/line-log.c\n@@ -894,14 +894,14 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang\n \tif (!pair || !diff)\n \t\treturn;\n \n-\tif (pair->one->sha1_valid)\n+\tif (pair->one->oid_valid)\n \t\tfill_line_ends(pair->one, &p_lines, &p_ends);\n \tfill_line_ends(pair->two, &t_lines, &t_ends);\n \n \tprintf(\"%s%sdiff --git a/%s b/%s%s\\n\", prefix, c_meta, pair->one->path, pair->two->path, c_reset);\n \tprintf(\"%s%s--- %s%s%s\\n\", prefix, c_meta,\n-\t       pair->one->sha1_valid ? \"a/\" : \"\",\n-\t       pair->one->sha1_valid ? pair->one->path : \"/dev/null\",\n+\t       pair->one->oid_valid ? \"a/\" : \"\",\n+\t       pair->one->oid_valid ? pair->one->path : \"/dev/null\",\n \t       c_reset);\n \tprintf(\"%s%s+++ b/%s%s\\n\", prefix, c_meta, pair->two->path, c_reset);\n \tfor (i = 0; i < range->ranges.nr; i++) {\n@@ -1011,12 +1011,12 @@ static int process_diff_filepair(struct rev_info *rev,\n \tif (rg->ranges.nr == 0)\n \t\treturn 0;\n \n-\tassert(pair->two->sha1_valid);\n+\tassert(pair->two->oid_valid);\n \tdiff_populate_filespec(pair->two, 0);\n \tfile_target.ptr = pair->two->data;\n \tfile_target.size = pair->two->size;\n \n-\tif (pair->one->sha1_valid) {\n+\tif (pair->one->oid_valid) {\n \t\tdiff_populate_filespec(pair->one, 0);\n \t\tfile_parent.ptr = pair->one->data;\n \t\tfile_parent.size = pair->one->size;\n"},{"id":"289587","messageId":"20160618221407.1046188-3-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"[PATCH v2 2/8] Apply object_id Coccinelle transformations.","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:14:01Z","receivedAt":"2016-06-18T22:14:33Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Apply the set of semantic patches from contrib/examples/coccinelle to\nconvert some leftover places using struct object_id's hash member to\ninstead use the wrapper functions that take struct object_id natively.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n bisect.c             |  2 +-\n builtin/merge.c      | 13 ++++++-------\n refs/files-backend.c |  4 ++--\n 3 files changed, 9 insertions(+), 10 deletions(-)\n\ndiff --git a/bisect.c b/bisect.c\nindex 6d93edbc..ff147589 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -754,7 +754,7 @@ static void handle_bad_merge_base(void)\n static void handle_skipped_merge_base(const unsigned char *mb)\n {\n \tchar *mb_hex = sha1_to_hex(mb);\n-\tchar *bad_hex = sha1_to_hex(current_bad_oid->hash);\n+\tchar *bad_hex = oid_to_hex(current_bad_oid);\n \tchar *good_hex = join_sha1_array_hex(&good_revs, ' ');\n \n \twarning(\"the merge base between %s and [%s] \"\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex b555a1bf..1e7be852 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -501,7 +501,7 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \t\tif (ref_exists(truname.buf)) {\n \t\t\tstrbuf_addf(msg,\n \t\t\t\t    \"%s\\t\\tbranch '%s'%s of .\\n\",\n-\t\t\t\t    sha1_to_hex(remote_head->object.oid.hash),\n+\t\t\t\t    oid_to_hex(&remote_head->object.oid),\n \t\t\t\t    truname.buf + 11,\n \t\t\t\t    (early ? \" (early part)\" : \"\"));\n \t\t\tstrbuf_release(&truname);\n@@ -515,7 +515,7 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \t\tdesc = merge_remote_util(remote_head);\n \t\tif (desc && desc->obj && desc->obj->type == OBJ_TAG) {\n \t\t\tstrbuf_addf(msg, \"%s\\t\\t%s '%s'\\n\",\n-\t\t\t\t    sha1_to_hex(desc->obj->oid.hash),\n+\t\t\t\t    oid_to_hex(&desc->obj->oid),\n \t\t\t\t    typename(desc->obj->type),\n \t\t\t\t    remote);\n \t\t\tgoto cleanup;\n@@ -523,7 +523,7 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \t}\n \n \tstrbuf_addf(msg, \"%s\\t\\tcommit '%s'\\n\",\n-\t\tsha1_to_hex(remote_head->object.oid.hash), remote);\n+\t\toid_to_hex(&remote_head->object.oid), remote);\n cleanup:\n \tstrbuf_release(&buf);\n \tstrbuf_release(&bname);\n@@ -1366,7 +1366,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \tfor (p = remoteheads; p; p = p->next) {\n \t\tstruct commit *commit = p->item;\n \t\tstrbuf_addf(&buf, \"GITHEAD_%s\",\n-\t\t\t    sha1_to_hex(commit->object.oid.hash));\n+\t\t\t    oid_to_hex(&commit->object.oid));\n \t\tsetenv(buf.buf, merge_remote_util(commit)->name, 1);\n \t\tstrbuf_reset(&buf);\n \t\tif (fast_forward != FF_ONLY &&\n@@ -1425,7 +1425,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tgoto done;\n \t} else if (fast_forward != FF_NO && !remoteheads->next &&\n \t\t\t!common->next &&\n-\t\t\t!hashcmp(common->item->object.oid.hash, head_commit->object.oid.hash)) {\n+\t\t\t!oidcmp(&common->item->object.oid, &head_commit->object.oid)) {\n \t\t/* Again the most common case of merging one remote. */\n \t\tstruct strbuf msg = STRBUF_INIT;\n \t\tstruct commit *commit;\n@@ -1499,8 +1499,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t\t * HEAD^^\" would be missed.\n \t\t\t */\n \t\t\tcommon_one = get_merge_bases(head_commit, j->item);\n-\t\t\tif (hashcmp(common_one->item->object.oid.hash,\n-\t\t\t\tj->item->object.oid.hash)) {\n+\t\t\tif (oidcmp(&common_one->item->object.oid, &j->item->object.oid)) {\n \t\t\t\tup_to_date = 0;\n \t\t\t\tbreak;\n \t\t\t}\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 1f380764..dac3a222 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1725,14 +1725,14 @@ static int verify_lock(struct ref_lock *lock,\n \t\t\terrno = save_errno;\n \t\t\treturn -1;\n \t\t} else {\n-\t\t\thashclr(lock->old_oid.hash);\n+\t\t\toidclr(&lock->old_oid);\n \t\t\treturn 0;\n \t\t}\n \t}\n \tif (old_sha1 && hashcmp(lock->old_oid.hash, old_sha1)) {\n \t\tstrbuf_addf(err, \"ref %s is at %s but expected %s\",\n \t\t\t    lock->ref_name,\n-\t\t\t    sha1_to_hex(lock->old_oid.hash),\n+\t\t\t    oid_to_hex(&lock->old_oid),\n \t\t\t    sha1_to_hex(old_sha1));\n \t\terrno = EBUSY;\n \t\treturn -1;\n"},{"id":"289588","messageId":"20160618221407.1046188-9-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"[PATCH v2 8/8] merge-recursive: convert merge_recursive_generic to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:14:07Z","receivedAt":"2016-06-18T22:14:35Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert this function and the git merge-recursive subcommand to use\nstruct object_id.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/merge-recursive.c | 20 ++++++++++----------\n merge-recursive.c         | 14 +++++++-------\n merge-recursive.h         |  6 +++---\n 3 files changed, 20 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c\nindex 491efd55..fd2c4556 100644\n--- a/builtin/merge-recursive.c\n+++ b/builtin/merge-recursive.c\n@@ -9,10 +9,10 @@ static const char builtin_merge_recursive_usage[] =\n \n static const char *better_branch_name(const char *branch)\n {\n-\tstatic char githead_env[8 + 40 + 1];\n+\tstatic char githead_env[8 + GIT_SHA1_HEXSZ + 1];\n \tchar *name;\n \n-\tif (strlen(branch) != 40)\n+\tif (strlen(branch) != GIT_SHA1_HEXSZ)\n \t\treturn branch;\n \txsnprintf(githead_env, sizeof(githead_env), \"GITHEAD_%s\", branch);\n \tname = getenv(githead_env);\n@@ -21,10 +21,10 @@ static const char *better_branch_name(const char *branch)\n \n int cmd_merge_recursive(int argc, const char **argv, const char *prefix)\n {\n-\tconst unsigned char *bases[21];\n+\tconst struct object_id *bases[21];\n \tunsigned bases_count = 0;\n \tint i, failed;\n-\tunsigned char h1[20], h2[20];\n+\tstruct object_id h1, h2;\n \tstruct merge_options o;\n \tstruct commit *result;\n \n@@ -46,10 +46,10 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \t\t}\n \t\tif (bases_count < ARRAY_SIZE(bases)-1) {\n-\t\t\tunsigned char *sha = xmalloc(20);\n-\t\t\tif (get_sha1(argv[i], sha))\n+\t\t\tstruct object_id *oid = xmalloc(sizeof(struct object_id));\n+\t\t\tif (get_oid(argv[i], oid))\n \t\t\t\tdie(\"Could not parse object '%s'\", argv[i]);\n-\t\t\tbases[bases_count++] = sha;\n+\t\t\tbases[bases_count++] = oid;\n \t\t}\n \t\telse\n \t\t\twarning(\"Cannot handle more than %d bases. \"\n@@ -62,9 +62,9 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)\n \to.branch1 = argv[++i];\n \to.branch2 = argv[++i];\n \n-\tif (get_sha1(o.branch1, h1))\n+\tif (get_oid(o.branch1, &h1))\n \t\tdie(\"Could not resolve ref '%s'\", o.branch1);\n-\tif (get_sha1(o.branch2, h2))\n+\tif (get_oid(o.branch2, &h2))\n \t\tdie(\"Could not resolve ref '%s'\", o.branch2);\n \n \to.branch1 = better_branch_name(o.branch1);\n@@ -73,7 +73,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)\n \tif (o.verbosity >= 3)\n \t\tprintf(\"Merging %s with %s\\n\", o.branch1, o.branch2);\n \n-\tfailed = merge_recursive_generic(&o, h1, h2, bases_count, bases, &result);\n+\tfailed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result);\n \tif (failed < 0)\n \t\treturn 128; /* die() error code */\n \treturn failed;\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 7bbd4aea..48fe7e73 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1982,11 +1982,11 @@ int merge_recursive(struct merge_options *o,\n \treturn clean;\n }\n \n-static struct commit *get_ref(const unsigned char *sha1, const char *name)\n+static struct commit *get_ref(const struct object_id *oid, const char *name)\n {\n \tstruct object *object;\n \n-\tobject = deref_tag(parse_object(sha1), name, strlen(name));\n+\tobject = deref_tag(parse_object(oid->hash), name, strlen(name));\n \tif (!object)\n \t\treturn NULL;\n \tif (object->type == OBJ_TREE)\n@@ -1999,10 +1999,10 @@ static struct commit *get_ref(const unsigned char *sha1, const char *name)\n }\n \n int merge_recursive_generic(struct merge_options *o,\n-\t\t\t    const unsigned char *head,\n-\t\t\t    const unsigned char *merge,\n+\t\t\t    const struct object_id *head,\n+\t\t\t    const struct object_id *merge,\n \t\t\t    int num_base_list,\n-\t\t\t    const unsigned char **base_list,\n+\t\t\t    const struct object_id **base_list,\n \t\t\t    struct commit **result)\n {\n \tint clean;\n@@ -2015,9 +2015,9 @@ int merge_recursive_generic(struct merge_options *o,\n \t\tint i;\n \t\tfor (i = 0; i < num_base_list; ++i) {\n \t\t\tstruct commit *base;\n-\t\t\tif (!(base = get_ref(base_list[i], sha1_to_hex(base_list[i]))))\n+\t\t\tif (!(base = get_ref(base_list[i], oid_to_hex(base_list[i]))))\n \t\t\t\treturn error(_(\"Could not parse object '%s'\"),\n-\t\t\t\t\tsha1_to_hex(base_list[i]));\n+\t\t\t\t\toid_to_hex(base_list[i]));\n \t\t\tcommit_list_insert(base, &ca);\n \t\t}\n \t}\ndiff --git a/merge-recursive.h b/merge-recursive.h\nindex 52f0201f..d415724a 100644\n--- a/merge-recursive.h\n+++ b/merge-recursive.h\n@@ -49,10 +49,10 @@ int merge_trees(struct merge_options *o,\n  * virtual commits and call merge_recursive() proper.\n  */\n int merge_recursive_generic(struct merge_options *o,\n-\t\t\t    const unsigned char *head,\n-\t\t\t    const unsigned char *merge,\n+\t\t\t    const struct object_id *head,\n+\t\t\t    const struct object_id *merge,\n \t\t\t    int num_ca,\n-\t\t\t    const unsigned char **ca,\n+\t\t\t    const struct object_id **ca,\n \t\t\t    struct commit **result);\n \n void init_merge_options(struct merge_options *o);\n"},{"id":"289589","messageId":"20160618221407.1046188-8-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"[PATCH v2 7/8] merge-recursive: convert leaf functions to use struct object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:14:06Z","receivedAt":"2016-06-18T22:14:35Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert all but two of the static functions in this file to use struct\nobject_id.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n merge-recursive.c | 236 +++++++++++++++++++++++++++---------------------------\n 1 file changed, 118 insertions(+), 118 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex bc455491..7bbd4aea 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -56,11 +56,11 @@ static struct commit *make_virtual_commit(struct tree *tree, const char *comment\n  * Since we use get_tree_entry(), which does not put the read object into\n  * the object pool, we cannot rely on a == b.\n  */\n-static int sha_eq(const unsigned char *a, const unsigned char *b)\n+static int oid_eq(const struct object_id *a, const struct object_id *b)\n {\n \tif (!a && !b)\n \t\treturn 2;\n-\treturn a && b && hashcmp(a, b) == 0;\n+\treturn a && b && oidcmp(a, b) == 0;\n }\n \n enum rename_type {\n@@ -198,11 +198,11 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)\n \t}\n }\n \n-static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,\n+static int add_cacheinfo(unsigned int mode, const struct object_id *oid,\n \t\tconst char *path, int stage, int refresh, int options)\n {\n \tstruct cache_entry *ce;\n-\tce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage,\n+\tce = make_cache_entry(mode, oid ? oid->hash : null_sha1, path, stage,\n \t\t\t      (refresh ? (CE_MATCH_REFRESH |\n \t\t\t\t\t  CE_MATCH_IGNORE_MISSING) : 0 ));\n \tif (!ce)\n@@ -552,13 +552,13 @@ static int update_stages(const char *path, const struct diff_filespec *o,\n \t\tif (remove_file_from_cache(path))\n \t\t\treturn -1;\n \tif (o)\n-\t\tif (add_cacheinfo(o->mode, o->oid.hash, path, 1, 0, options))\n+\t\tif (add_cacheinfo(o->mode, &o->oid, path, 1, 0, options))\n \t\t\treturn -1;\n \tif (a)\n-\t\tif (add_cacheinfo(a->mode, a->oid.hash, path, 2, 0, options))\n+\t\tif (add_cacheinfo(a->mode, &a->oid, path, 2, 0, options))\n \t\t\treturn -1;\n \tif (b)\n-\t\tif (add_cacheinfo(b->mode, b->oid.hash, path, 3, 0, options))\n+\t\tif (add_cacheinfo(b->mode, &b->oid, path, 3, 0, options))\n \t\t\treturn -1;\n \treturn 0;\n }\n@@ -736,7 +736,7 @@ static int make_room_for_path(struct merge_options *o, const char *path)\n }\n \n static void update_file_flags(struct merge_options *o,\n-\t\t\t      const unsigned char *sha,\n+\t\t\t      const struct object_id *oid,\n \t\t\t      unsigned mode,\n \t\t\t      const char *path,\n \t\t\t      int update_cache,\n@@ -760,11 +760,11 @@ static void update_file_flags(struct merge_options *o,\n \t\t\tgoto update_index;\n \t\t}\n \n-\t\tbuf = read_sha1_file(sha, &type, &size);\n+\t\tbuf = read_sha1_file(oid->hash, &type, &size);\n \t\tif (!buf)\n-\t\t\tdie(_(\"cannot read object %s '%s'\"), sha1_to_hex(sha), path);\n+\t\t\tdie(_(\"cannot read object %s '%s'\"), oid_to_hex(oid), path);\n \t\tif (type != OBJ_BLOB)\n-\t\t\tdie(_(\"blob expected for %s '%s'\"), sha1_to_hex(sha), path);\n+\t\t\tdie(_(\"blob expected for %s '%s'\"), oid_to_hex(oid), path);\n \t\tif (S_ISREG(mode)) {\n \t\t\tstruct strbuf strbuf = STRBUF_INIT;\n \t\t\tif (convert_to_working_tree(path, buf, size, &strbuf)) {\n@@ -799,21 +799,21 @@ static void update_file_flags(struct merge_options *o,\n \t\t\tfree(lnk);\n \t\t} else\n \t\t\tdie(_(\"do not know what to do with %06o %s '%s'\"),\n-\t\t\t    mode, sha1_to_hex(sha), path);\n+\t\t\t    mode, oid_to_hex(oid), path);\n \t\tfree(buf);\n \t}\n  update_index:\n \tif (update_cache)\n-\t\tadd_cacheinfo(mode, sha, path, 0, update_wd, ADD_CACHE_OK_TO_ADD);\n+\t\tadd_cacheinfo(mode, oid, path, 0, update_wd, ADD_CACHE_OK_TO_ADD);\n }\n \n static void update_file(struct merge_options *o,\n \t\t\tint clean,\n-\t\t\tconst unsigned char *sha,\n+\t\t\tconst struct object_id *oid,\n \t\t\tunsigned mode,\n \t\t\tconst char *path)\n {\n-\tupdate_file_flags(o, sha, mode, path, o->call_depth || clean, !o->call_depth);\n+\tupdate_file_flags(o, oid, mode, path, o->call_depth || clean, !o->call_depth);\n }\n \n /* Low level file merging, update and removal */\n@@ -908,7 +908,7 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\t\toidcpy(&result.oid, &b->oid);\n \t\t}\n \t} else {\n-\t\tif (!sha_eq(a->oid.hash, one->oid.hash) && !sha_eq(b->oid.hash, one->oid.hash))\n+\t\tif (!oid_eq(&a->oid, &one->oid) && !oid_eq(&b->oid, &one->oid))\n \t\t\tresult.merge = 1;\n \n \t\t/*\n@@ -924,9 +924,9 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\t\t}\n \t\t}\n \n-\t\tif (sha_eq(a->oid.hash, b->oid.hash) || sha_eq(a->oid.hash, one->oid.hash))\n+\t\tif (oid_eq(&a->oid, &b->oid) || oid_eq(&a->oid, &one->oid))\n \t\t\toidcpy(&result.oid, &b->oid);\n-\t\telse if (sha_eq(b->oid.hash, one->oid.hash))\n+\t\telse if (oid_eq(&b->oid, &one->oid))\n \t\t\toidcpy(&result.oid, &a->oid);\n \t\telse if (S_ISREG(a->mode)) {\n \t\t\tmmbuffer_t result_buf;\n@@ -955,7 +955,7 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\t} else if (S_ISLNK(a->mode)) {\n \t\t\toidcpy(&result.oid, &a->oid);\n \n-\t\t\tif (!sha_eq(a->oid.hash, b->oid.hash))\n+\t\t\tif (!oid_eq(&a->oid, &b->oid))\n \t\t\t\tresult.clean = 0;\n \t\t} else {\n \t\t\tdie(_(\"unsupported object type in the tree\"));\n@@ -993,34 +993,34 @@ merge_file_special_markers(struct merge_options *o,\n \n static struct merge_file_info merge_file_one(struct merge_options *o,\n \t\t\t\t\t const char *path,\n-\t\t\t\t\t const unsigned char *o_sha, int o_mode,\n-\t\t\t\t\t const unsigned char *a_sha, int a_mode,\n-\t\t\t\t\t const unsigned char *b_sha, int b_mode,\n+\t\t\t\t\t const struct object_id *o_oid, int o_mode,\n+\t\t\t\t\t const struct object_id *a_oid, int a_mode,\n+\t\t\t\t\t const struct object_id *b_oid, int b_mode,\n \t\t\t\t\t const char *branch1,\n \t\t\t\t\t const char *branch2)\n {\n \tstruct diff_filespec one, a, b;\n \n \tone.path = a.path = b.path = (char *)path;\n-\thashcpy(one.oid.hash, o_sha);\n+\toidcpy(&one.oid, o_oid);\n \tone.mode = o_mode;\n-\thashcpy(a.oid.hash, a_sha);\n+\toidcpy(&a.oid, a_oid);\n \ta.mode = a_mode;\n-\thashcpy(b.oid.hash, b_sha);\n+\toidcpy(&b.oid, b_oid);\n \tb.mode = b_mode;\n \treturn merge_file_1(o, &one, &a, &b, branch1, branch2);\n }\n \n static void handle_change_delete(struct merge_options *o,\n \t\t\t\t const char *path,\n-\t\t\t\t const unsigned char *o_sha, int o_mode,\n-\t\t\t\t const unsigned char *a_sha, int a_mode,\n-\t\t\t\t const unsigned char *b_sha, int b_mode,\n+\t\t\t\t const struct object_id *o_oid, int o_mode,\n+\t\t\t\t const struct object_id *a_oid, int a_mode,\n+\t\t\t\t const struct object_id *b_oid, int b_mode,\n \t\t\t\t const char *change, const char *change_past)\n {\n \tchar *renamed = NULL;\n \tif (dir_in_way(path, !o->call_depth)) {\n-\t\trenamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2);\n+\t\trenamed = unique_path(o, path, a_oid ? o->branch1 : o->branch2);\n \t}\n \n \tif (o->call_depth) {\n@@ -1030,20 +1030,20 @@ static void handle_change_delete(struct merge_options *o,\n \t\t * them, simply reuse the base version for virtual merge base.\n \t\t */\n \t\tremove_file_from_cache(path);\n-\t\tupdate_file(o, 0, o_sha, o_mode, renamed ? renamed : path);\n-\t} else if (!a_sha) {\n+\t\tupdate_file(o, 0, o_oid, o_mode, renamed ? renamed : path);\n+\t} else if (!a_oid) {\n \t\tif (!renamed) {\n \t\t\toutput(o, 1, _(\"CONFLICT (%s/delete): %s deleted in %s \"\n \t\t\t       \"and %s in %s. Version %s of %s left in tree.\"),\n \t\t\t       change, path, o->branch1, change_past,\n \t\t\t       o->branch2, o->branch2, path);\n-\t\t\tupdate_file(o, 0, b_sha, b_mode, path);\n+\t\t\tupdate_file(o, 0, b_oid, b_mode, path);\n \t\t} else {\n \t\t\toutput(o, 1, _(\"CONFLICT (%s/delete): %s deleted in %s \"\n \t\t\t       \"and %s in %s. Version %s of %s left in tree at %s.\"),\n \t\t\t       change, path, o->branch1, change_past,\n \t\t\t       o->branch2, o->branch2, path, renamed);\n-\t\t\tupdate_file(o, 0, b_sha, b_mode, renamed);\n+\t\t\tupdate_file(o, 0, b_oid, b_mode, renamed);\n \t\t}\n \t} else {\n \t\tif (!renamed) {\n@@ -1056,7 +1056,7 @@ static void handle_change_delete(struct merge_options *o,\n \t\t\t       \"and %s in %s. Version %s of %s left in tree at %s.\"),\n \t\t\t       change, path, o->branch2, change_past,\n \t\t\t       o->branch1, o->branch1, path, renamed);\n-\t\t\tupdate_file(o, 0, a_sha, a_mode, renamed);\n+\t\t\tupdate_file(o, 0, a_oid, a_mode, renamed);\n \t\t}\n \t\t/*\n \t\t * No need to call update_file() on path when !renamed, since\n@@ -1075,24 +1075,24 @@ static void conflict_rename_delete(struct merge_options *o,\n {\n \tconst struct diff_filespec *orig = pair->one;\n \tconst struct diff_filespec *dest = pair->two;\n-\tconst unsigned char *a_sha = NULL;\n-\tconst unsigned char *b_sha = NULL;\n+\tconst struct object_id *a_oid = NULL;\n+\tconst struct object_id *b_oid = NULL;\n \tint a_mode = 0;\n \tint b_mode = 0;\n \n \tif (rename_branch == o->branch1) {\n-\t\ta_sha = dest->oid.hash;\n+\t\ta_oid = &dest->oid;\n \t\ta_mode = dest->mode;\n \t} else {\n-\t\tb_sha = dest->oid.hash;\n+\t\tb_oid = &dest->oid;\n \t\tb_mode = dest->mode;\n \t}\n \n \thandle_change_delete(o,\n \t\t\t     o->call_depth ? orig->path : dest->path,\n-\t\t\t     orig->oid.hash, orig->mode,\n-\t\t\t     a_sha, a_mode,\n-\t\t\t     b_sha, b_mode,\n+\t\t\t     &orig->oid, orig->mode,\n+\t\t\t     a_oid, a_mode,\n+\t\t\t     b_oid, b_mode,\n \t\t\t     _(\"rename\"), _(\"renamed\"));\n \n \tif (o->call_depth) {\n@@ -1109,11 +1109,11 @@ static struct diff_filespec *filespec_from_entry(struct diff_filespec *target,\n \t\t\t\t\t\t struct stage_data *entry,\n \t\t\t\t\t\t int stage)\n {\n-\tunsigned char *sha = entry->stages[stage].oid.hash;\n+\tstruct object_id *oid = &entry->stages[stage].oid;\n \tunsigned mode = entry->stages[stage].mode;\n-\tif (mode == 0 || is_null_sha1(sha))\n+\tif (mode == 0 || is_null_oid(oid))\n \t\treturn NULL;\n-\thashcpy(target->oid.hash, sha);\n+\toidcpy(&target->oid, oid);\n \ttarget->mode = mode;\n \treturn target;\n }\n@@ -1142,7 +1142,7 @@ static void handle_file(struct merge_options *o,\n \tadd = filespec_from_entry(&other, dst_entry, stage ^ 1);\n \tif (add) {\n \t\tchar *add_name = unique_path(o, rename->path, other_branch);\n-\t\tupdate_file(o, 0, add->oid.hash, add->mode, add_name);\n+\t\tupdate_file(o, 0, &add->oid, add->mode, add_name);\n \n \t\tremove_file(o, 0, rename->path, 0);\n \t\tdst_name = unique_path(o, rename->path, cur_branch);\n@@ -1153,7 +1153,7 @@ static void handle_file(struct merge_options *o,\n \t\t\t       rename->path, other_branch, dst_name);\n \t\t}\n \t}\n-\tupdate_file(o, 0, rename->oid.hash, rename->mode, dst_name);\n+\tupdate_file(o, 0, &rename->oid, rename->mode, dst_name);\n \tif (stage == 2)\n \t\tupdate_stages(rename->path, NULL, rename, add);\n \telse\n@@ -1182,9 +1182,9 @@ static void conflict_rename_rename_1to2(struct merge_options *o,\n \t\tstruct diff_filespec other;\n \t\tstruct diff_filespec *add;\n \t\tmfi = merge_file_one(o, one->path,\n-\t\t\t\t one->oid.hash, one->mode,\n-\t\t\t\t a->oid.hash, a->mode,\n-\t\t\t\t b->oid.hash, b->mode,\n+\t\t\t\t &one->oid, one->mode,\n+\t\t\t\t &a->oid, a->mode,\n+\t\t\t\t &b->oid, b->mode,\n \t\t\t\t ci->branch1, ci->branch2);\n \t\t/*\n \t\t * FIXME: For rename/add-source conflicts (if we could detect\n@@ -1192,7 +1192,7 @@ static void conflict_rename_rename_1to2(struct merge_options *o,\n \t\t * pathname and then either rename the add-source file to that\n \t\t * unique path, or use that unique path instead of src here.\n \t\t */\n-\t\tupdate_file(o, 0, mfi.oid.hash, mfi.mode, one->path);\n+\t\tupdate_file(o, 0, &mfi.oid, mfi.mode, one->path);\n \n \t\t/*\n \t\t * Above, we put the merged content at the merge-base's\n@@ -1204,12 +1204,12 @@ static void conflict_rename_rename_1to2(struct merge_options *o,\n \t\t */\n \t\tadd = filespec_from_entry(&other, ci->dst_entry1, 2 ^ 1);\n \t\tif (add)\n-\t\t\tupdate_file(o, 0, add->oid.hash, add->mode, a->path);\n+\t\t\tupdate_file(o, 0, &add->oid, add->mode, a->path);\n \t\telse\n \t\t\tremove_file_from_cache(a->path);\n \t\tadd = filespec_from_entry(&other, ci->dst_entry2, 3 ^ 1);\n \t\tif (add)\n-\t\t\tupdate_file(o, 0, add->oid.hash, add->mode, b->path);\n+\t\t\tupdate_file(o, 0, &add->oid, add->mode, b->path);\n \t\telse\n \t\t\tremove_file_from_cache(b->path);\n \t} else {\n@@ -1255,16 +1255,16 @@ static void conflict_rename_rename_2to1(struct merge_options *o,\n \t\t * again later for the non-recursive merge.\n \t\t */\n \t\tremove_file(o, 0, path, 0);\n-\t\tupdate_file(o, 0, mfi_c1.oid.hash, mfi_c1.mode, a->path);\n-\t\tupdate_file(o, 0, mfi_c2.oid.hash, mfi_c2.mode, b->path);\n+\t\tupdate_file(o, 0, &mfi_c1.oid, mfi_c1.mode, a->path);\n+\t\tupdate_file(o, 0, &mfi_c2.oid, mfi_c2.mode, b->path);\n \t} else {\n \t\tchar *new_path1 = unique_path(o, path, ci->branch1);\n \t\tchar *new_path2 = unique_path(o, path, ci->branch2);\n \t\toutput(o, 1, _(\"Renaming %s to %s and %s to %s instead\"),\n \t\t       a->path, new_path1, b->path, new_path2);\n \t\tremove_file(o, 0, path, 0);\n-\t\tupdate_file(o, 0, mfi_c1.oid.hash, mfi_c1.mode, new_path1);\n-\t\tupdate_file(o, 0, mfi_c2.oid.hash, mfi_c2.mode, new_path2);\n+\t\tupdate_file(o, 0, &mfi_c1.oid, mfi_c1.mode, new_path1);\n+\t\tupdate_file(o, 0, &mfi_c2.oid, mfi_c2.mode, new_path2);\n \t\tfree(new_path2);\n \t\tfree(new_path1);\n \t}\n@@ -1431,7 +1431,7 @@ static int process_renames(struct merge_options *o,\n \t\t\tdst_other.mode = ren1->dst_entry->stages[other_stage].mode;\n \t\t\ttry_merge = 0;\n \n-\t\t\tif (sha_eq(src_other.oid.hash, null_sha1)) {\n+\t\t\tif (oid_eq(&src_other.oid, &null_oid)) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_DELETE,\n \t\t\t\t\t\t\t   ren1->pair,\n \t\t\t\t\t\t\t   NULL,\n@@ -1443,7 +1443,7 @@ static int process_renames(struct merge_options *o,\n \t\t\t\t\t\t\t   NULL,\n \t\t\t\t\t\t\t   NULL);\n \t\t\t} else if ((dst_other.mode == ren1->pair->two->mode) &&\n-\t\t\t\t   sha_eq(dst_other.oid.hash, ren1->pair->two->oid.hash)) {\n+\t\t\t\t   oid_eq(&dst_other.oid, &ren1->pair->two->oid)) {\n \t\t\t\t/*\n \t\t\t\t * Added file on the other side identical to\n \t\t\t\t * the file being renamed: clean merge.\n@@ -1453,12 +1453,12 @@ static int process_renames(struct merge_options *o,\n \t\t\t\t * update_file().\n \t\t\t\t */\n \t\t\t\tupdate_file_flags(o,\n-\t\t\t\t\t\t  ren1->pair->two->oid.hash,\n+\t\t\t\t\t\t  &ren1->pair->two->oid,\n \t\t\t\t\t\t  ren1->pair->two->mode,\n \t\t\t\t\t\t  ren1_dst,\n \t\t\t\t\t\t  1, /* update_cache */\n \t\t\t\t\t\t  0  /* update_wd    */);\n-\t\t\t} else if (!sha_eq(dst_other.oid.hash, null_sha1)) {\n+\t\t\t} else if (!oid_eq(&dst_other.oid, &null_oid)) {\n \t\t\t\tclean_merge = 0;\n \t\t\t\ttry_merge = 1;\n \t\t\t\toutput(o, 1, _(\"CONFLICT (rename/add): Rename %s->%s in %s. \"\n@@ -1467,20 +1467,20 @@ static int process_renames(struct merge_options *o,\n \t\t\t\t       ren1_dst, branch2);\n \t\t\t\tif (o->call_depth) {\n \t\t\t\t\tstruct merge_file_info mfi;\n-\t\t\t\t\tmfi = merge_file_one(o, ren1_dst, null_sha1, 0,\n-\t\t\t\t\t\t\t ren1->pair->two->oid.hash,\n+\t\t\t\t\tmfi = merge_file_one(o, ren1_dst, &null_oid, 0,\n+\t\t\t\t\t\t\t &ren1->pair->two->oid,\n \t\t\t\t\t\t\t ren1->pair->two->mode,\n-\t\t\t\t\t\t\t dst_other.oid.hash,\n+\t\t\t\t\t\t\t &dst_other.oid,\n \t\t\t\t\t\t\t dst_other.mode,\n \t\t\t\t\t\t\t branch1, branch2);\n \t\t\t\t\toutput(o, 1, _(\"Adding merged %s\"), ren1_dst);\n-\t\t\t\t\tupdate_file(o, 0, mfi.oid.hash,\n+\t\t\t\t\tupdate_file(o, 0, &mfi.oid,\n \t\t\t\t\t\t    mfi.mode, ren1_dst);\n \t\t\t\t\ttry_merge = 0;\n \t\t\t\t} else {\n \t\t\t\t\tchar *new_path = unique_path(o, ren1_dst, branch2);\n \t\t\t\t\toutput(o, 1, _(\"Adding as %s instead\"), new_path);\n-\t\t\t\t\tupdate_file(o, 0, dst_other.oid.hash,\n+\t\t\t\t\tupdate_file(o, 0, &dst_other.oid,\n \t\t\t\t\t\t    dst_other.mode, new_path);\n \t\t\t\t\tfree(new_path);\n \t\t\t\t}\n@@ -1519,30 +1519,30 @@ static int process_renames(struct merge_options *o,\n \treturn clean_merge;\n }\n \n-static unsigned char *stage_sha(const unsigned char *sha, unsigned mode)\n+static struct object_id *stage_oid(const struct object_id *oid, unsigned mode)\n {\n-\treturn (is_null_sha1(sha) || mode == 0) ? NULL: (unsigned char *)sha;\n+\treturn (is_null_oid(oid) || mode == 0) ? NULL: (struct object_id *)oid;\n }\n \n-static int read_sha1_strbuf(const unsigned char *sha1, struct strbuf *dst)\n+static int read_oid_strbuf(const struct object_id *oid, struct strbuf *dst)\n {\n \tvoid *buf;\n \tenum object_type type;\n \tunsigned long size;\n-\tbuf = read_sha1_file(sha1, &type, &size);\n+\tbuf = read_sha1_file(oid->hash, &type, &size);\n \tif (!buf)\n-\t\treturn error(_(\"cannot read object %s\"), sha1_to_hex(sha1));\n+\t\treturn error(_(\"cannot read object %s\"), oid_to_hex(oid));\n \tif (type != OBJ_BLOB) {\n \t\tfree(buf);\n-\t\treturn error(_(\"object %s is not a blob\"), sha1_to_hex(sha1));\n+\t\treturn error(_(\"object %s is not a blob\"), oid_to_hex(oid));\n \t}\n \tstrbuf_attach(dst, buf, size, size + 1);\n \treturn 0;\n }\n \n-static int blob_unchanged(const unsigned char *o_sha,\n+static int blob_unchanged(const struct object_id *o_oid,\n \t\t\t  unsigned o_mode,\n-\t\t\t  const unsigned char *a_sha,\n+\t\t\t  const struct object_id *a_oid,\n \t\t\t  unsigned a_mode,\n \t\t\t  int renormalize, const char *path)\n {\n@@ -1552,13 +1552,13 @@ static int blob_unchanged(const unsigned char *o_sha,\n \n \tif (a_mode != o_mode)\n \t\treturn 0;\n-\tif (sha_eq(o_sha, a_sha))\n+\tif (oid_eq(o_oid, a_oid))\n \t\treturn 1;\n \tif (!renormalize)\n \t\treturn 0;\n \n-\tassert(o_sha && a_sha);\n-\tif (read_sha1_strbuf(o_sha, &o) || read_sha1_strbuf(a_sha, &a))\n+\tassert(o_oid && a_oid);\n+\tif (read_oid_strbuf(o_oid, &o) || read_oid_strbuf(a_oid, &a))\n \t\tgoto error_return;\n \t/*\n \t * Note: binary | is used so that both renormalizations are\n@@ -1577,23 +1577,23 @@ error_return:\n \n static void handle_modify_delete(struct merge_options *o,\n \t\t\t\t const char *path,\n-\t\t\t\t unsigned char *o_sha, int o_mode,\n-\t\t\t\t unsigned char *a_sha, int a_mode,\n-\t\t\t\t unsigned char *b_sha, int b_mode)\n+\t\t\t\t struct object_id *o_oid, int o_mode,\n+\t\t\t\t struct object_id *a_oid, int a_mode,\n+\t\t\t\t struct object_id *b_oid, int b_mode)\n {\n \thandle_change_delete(o,\n \t\t\t     path,\n-\t\t\t     o_sha, o_mode,\n-\t\t\t     a_sha, a_mode,\n-\t\t\t     b_sha, b_mode,\n+\t\t\t     o_oid, o_mode,\n+\t\t\t     a_oid, a_mode,\n+\t\t\t     b_oid, b_mode,\n \t\t\t     _(\"modify\"), _(\"modified\"));\n }\n \n static int merge_content(struct merge_options *o,\n \t\t\t const char *path,\n-\t\t\t unsigned char *o_sha, int o_mode,\n-\t\t\t unsigned char *a_sha, int a_mode,\n-\t\t\t unsigned char *b_sha, int b_mode,\n+\t\t\t struct object_id *o_oid, int o_mode,\n+\t\t\t struct object_id *a_oid, int a_mode,\n+\t\t\t struct object_id *b_oid, int b_mode,\n \t\t\t struct rename_conflict_info *rename_conflict_info)\n {\n \tconst char *reason = _(\"content\");\n@@ -1602,16 +1602,16 @@ static int merge_content(struct merge_options *o,\n \tstruct diff_filespec one, a, b;\n \tunsigned df_conflict_remains = 0;\n \n-\tif (!o_sha) {\n+\tif (!o_oid) {\n \t\treason = _(\"add/add\");\n-\t\to_sha = (unsigned char *)null_sha1;\n+\t\to_oid = (struct object_id *)&null_oid;\n \t}\n \tone.path = a.path = b.path = (char *)path;\n-\thashcpy(one.oid.hash, o_sha);\n+\toidcpy(&one.oid, o_oid);\n \tone.mode = o_mode;\n-\thashcpy(a.oid.hash, a_sha);\n+\toidcpy(&a.oid, a_oid);\n \ta.mode = a_mode;\n-\thashcpy(b.oid.hash, b_sha);\n+\toidcpy(&b.oid, b_oid);\n \tb.mode = b_mode;\n \n \tif (rename_conflict_info) {\n@@ -1635,7 +1635,7 @@ static int merge_content(struct merge_options *o,\n \t\t\t\t\t o->branch2, path2);\n \n \tif (mfi.clean && !df_conflict_remains &&\n-\t    sha_eq(mfi.oid.hash, a_sha) && mfi.mode == a_mode) {\n+\t    oid_eq(&mfi.oid, a_oid) && mfi.mode == a_mode) {\n \t\tint path_renamed_outside_HEAD;\n \t\toutput(o, 3, _(\"Skipped %s (merged same as existing)\"), path);\n \t\t/*\n@@ -1646,7 +1646,7 @@ static int merge_content(struct merge_options *o,\n \t\t */\n \t\tpath_renamed_outside_HEAD = !path2 || !strcmp(path, path2);\n \t\tif (!path_renamed_outside_HEAD) {\n-\t\t\tadd_cacheinfo(mfi.mode, mfi.oid.hash, path,\n+\t\t\tadd_cacheinfo(mfi.mode, &mfi.oid, path,\n \t\t\t\t      0, (!o->call_depth), 0);\n \t\t\treturn mfi.clean;\n \t\t}\n@@ -1683,11 +1683,11 @@ static int merge_content(struct merge_options *o,\n \t\t}\n \t\tnew_path = unique_path(o, path, rename_conflict_info->branch1);\n \t\toutput(o, 1, _(\"Adding as %s instead\"), new_path);\n-\t\tupdate_file(o, 0, mfi.oid.hash, mfi.mode, new_path);\n+\t\tupdate_file(o, 0, &mfi.oid, mfi.mode, new_path);\n \t\tfree(new_path);\n \t\tmfi.clean = 0;\n \t} else {\n-\t\tupdate_file(o, mfi.clean, mfi.oid.hash, mfi.mode, path);\n+\t\tupdate_file(o, mfi.clean, &mfi.oid, mfi.mode, path);\n \t}\n \treturn mfi.clean;\n \n@@ -1702,9 +1702,9 @@ static int process_entry(struct merge_options *o,\n \tunsigned o_mode = entry->stages[1].mode;\n \tunsigned a_mode = entry->stages[2].mode;\n \tunsigned b_mode = entry->stages[3].mode;\n-\tunsigned char *o_sha = stage_sha(entry->stages[1].oid.hash, o_mode);\n-\tunsigned char *a_sha = stage_sha(entry->stages[2].oid.hash, a_mode);\n-\tunsigned char *b_sha = stage_sha(entry->stages[3].oid.hash, b_mode);\n+\tstruct object_id *o_oid = stage_oid(&entry->stages[1].oid, o_mode);\n+\tstruct object_id *a_oid = stage_oid(&entry->stages[2].oid, a_mode);\n+\tstruct object_id *b_oid = stage_oid(&entry->stages[3].oid, b_mode);\n \n \tentry->processed = 1;\n \tif (entry->rename_conflict_info) {\n@@ -1713,7 +1713,7 @@ static int process_entry(struct merge_options *o,\n \t\tcase RENAME_NORMAL:\n \t\tcase RENAME_ONE_FILE_TO_ONE:\n \t\t\tclean_merge = merge_content(o, path,\n-\t\t\t\t\t\t    o_sha, o_mode, a_sha, a_mode, b_sha, b_mode,\n+\t\t\t\t\t\t    o_oid, o_mode, a_oid, a_mode, b_oid, b_mode,\n \t\t\t\t\t\t    conflict_info);\n \t\t\tbreak;\n \t\tcase RENAME_DELETE:\n@@ -1734,45 +1734,45 @@ static int process_entry(struct merge_options *o,\n \t\t\tentry->processed = 0;\n \t\t\tbreak;\n \t\t}\n-\t} else if (o_sha && (!a_sha || !b_sha)) {\n+\t} else if (o_oid && (!a_oid || !b_oid)) {\n \t\t/* Case A: Deleted in one */\n-\t\tif ((!a_sha && !b_sha) ||\n-\t\t    (!b_sha && blob_unchanged(o_sha, o_mode, a_sha, a_mode, normalize, path)) ||\n-\t\t    (!a_sha && blob_unchanged(o_sha, o_mode, b_sha, b_mode, normalize, path))) {\n+\t\tif ((!a_oid && !b_oid) ||\n+\t\t    (!b_oid && blob_unchanged(o_oid, o_mode, a_oid, a_mode, normalize, path)) ||\n+\t\t    (!a_oid && blob_unchanged(o_oid, o_mode, b_oid, b_mode, normalize, path))) {\n \t\t\t/* Deleted in both or deleted in one and\n \t\t\t * unchanged in the other */\n-\t\t\tif (a_sha)\n+\t\t\tif (a_oid)\n \t\t\t\toutput(o, 2, _(\"Removing %s\"), path);\n \t\t\t/* do not touch working file if it did not exist */\n-\t\t\tremove_file(o, 1, path, !a_sha);\n+\t\t\tremove_file(o, 1, path, !a_oid);\n \t\t} else {\n \t\t\t/* Modify/delete; deleted side may have put a directory in the way */\n \t\t\tclean_merge = 0;\n-\t\t\thandle_modify_delete(o, path, o_sha, o_mode,\n-\t\t\t\t\t     a_sha, a_mode, b_sha, b_mode);\n+\t\t\thandle_modify_delete(o, path, o_oid, o_mode,\n+\t\t\t\t\t     a_oid, a_mode, b_oid, b_mode);\n \t\t}\n-\t} else if ((!o_sha && a_sha && !b_sha) ||\n-\t\t   (!o_sha && !a_sha && b_sha)) {\n+\t} else if ((!o_oid && a_oid && !b_oid) ||\n+\t\t   (!o_oid && !a_oid && b_oid)) {\n \t\t/* Case B: Added in one. */\n \t\t/* [nothing|directory] -> ([nothing|directory], file) */\n \n \t\tconst char *add_branch;\n \t\tconst char *other_branch;\n \t\tunsigned mode;\n-\t\tconst unsigned char *sha;\n+\t\tconst struct object_id *oid;\n \t\tconst char *conf;\n \n-\t\tif (a_sha) {\n+\t\tif (a_oid) {\n \t\t\tadd_branch = o->branch1;\n \t\t\tother_branch = o->branch2;\n \t\t\tmode = a_mode;\n-\t\t\tsha = a_sha;\n+\t\t\toid = a_oid;\n \t\t\tconf = _(\"file/directory\");\n \t\t} else {\n \t\t\tadd_branch = o->branch2;\n \t\t\tother_branch = o->branch1;\n \t\t\tmode = b_mode;\n-\t\t\tsha = b_sha;\n+\t\t\toid = b_oid;\n \t\t\tconf = _(\"directory/file\");\n \t\t}\n \t\tif (dir_in_way(path, !o->call_depth)) {\n@@ -1781,22 +1781,22 @@ static int process_entry(struct merge_options *o,\n \t\t\toutput(o, 1, _(\"CONFLICT (%s): There is a directory with name %s in %s. \"\n \t\t\t       \"Adding %s as %s\"),\n \t\t\t       conf, path, other_branch, path, new_path);\n-\t\t\tupdate_file(o, 0, sha, mode, new_path);\n+\t\t\tupdate_file(o, 0, oid, mode, new_path);\n \t\t\tif (o->call_depth)\n \t\t\t\tremove_file_from_cache(path);\n \t\t\tfree(new_path);\n \t\t} else {\n \t\t\toutput(o, 2, _(\"Adding %s\"), path);\n \t\t\t/* do not overwrite file if already present */\n-\t\t\tupdate_file_flags(o, sha, mode, path, 1, !a_sha);\n+\t\t\tupdate_file_flags(o, oid, mode, path, 1, !a_oid);\n \t\t}\n-\t} else if (a_sha && b_sha) {\n+\t} else if (a_oid && b_oid) {\n \t\t/* Case C: Added in both (check for same permissions) and */\n \t\t/* case D: Modified in both, but differently. */\n \t\tclean_merge = merge_content(o, path,\n-\t\t\t\t\t    o_sha, o_mode, a_sha, a_mode, b_sha, b_mode,\n+\t\t\t\t\t    o_oid, o_mode, a_oid, a_mode, b_oid, b_mode,\n \t\t\t\t\t    NULL);\n-\t} else if (!o_sha && !a_sha && !b_sha) {\n+\t} else if (!o_oid && !a_oid && !b_oid) {\n \t\t/*\n \t\t * this entry was deleted altogether. a_mode == 0 means\n \t\t * we had that path and want to actively remove it.\n@@ -1821,7 +1821,7 @@ int merge_trees(struct merge_options *o,\n \t\tcommon = shift_tree_object(head, common, o->subtree_shift);\n \t}\n \n-\tif (sha_eq(common->object.oid.hash, merge->object.oid.hash)) {\n+\tif (oid_eq(&common->object.oid, &merge->object.oid)) {\n \t\toutput(o, 0, _(\"Already up-to-date!\"));\n \t\t*result = head;\n \t\treturn 1;\n"},{"id":"289590","messageId":"20160618221407.1046188-6-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"[PATCH v2 5/8] merge-recursive: convert struct stage_data to use object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:14:04Z","receivedAt":"2016-06-18T22:14:35Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert the anonymous struct within struct stage_data to use struct\nobject_id.  The following Coccinelle semantic patch was used to\nimplement this, followed by the transformations in object_id.cocci:\n\n@@\nstruct stage_data o;\nexpression E1;\n@@\n- o.stages[E1].sha\n+ o.stages[E1].oid.hash\n\n@@\nstruct stage_data *p;\nexpression E1;\n@@\n- p->stages[E1].sha\n+ p->stages[E1].oid.hash\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n merge-recursive.c | 38 ++++++++++++++++++--------------------\n 1 file changed, 18 insertions(+), 20 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 1e802097..a07050cd 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -90,7 +90,7 @@ struct rename_conflict_info {\n struct stage_data {\n \tstruct {\n \t\tunsigned mode;\n-\t\tunsigned char sha[20];\n+\t\tstruct object_id oid;\n \t} stages[4];\n \tstruct rename_conflict_info *rename_conflict_info;\n \tunsigned processed:1;\n@@ -134,13 +134,11 @@ static inline void setup_rename_conflict_info(enum rename_type rename_type,\n \t\tint ostage2 = ostage1 ^ 1;\n \n \t\tci->ren1_other.path = pair1->one->path;\n-\t\thashcpy(ci->ren1_other.oid.hash,\n-\t\t\tsrc_entry1->stages[ostage1].sha);\n+\t\toidcpy(&ci->ren1_other.oid, &src_entry1->stages[ostage1].oid);\n \t\tci->ren1_other.mode = src_entry1->stages[ostage1].mode;\n \n \t\tci->ren2_other.path = pair2->one->path;\n-\t\thashcpy(ci->ren2_other.oid.hash,\n-\t\t\tsrc_entry2->stages[ostage2].sha);\n+\t\toidcpy(&ci->ren2_other.oid, &src_entry2->stages[ostage2].oid);\n \t\tci->ren2_other.mode = src_entry2->stages[ostage2].mode;\n \t}\n }\n@@ -316,11 +314,11 @@ static struct stage_data *insert_stage_data(const char *path,\n \tstruct string_list_item *item;\n \tstruct stage_data *e = xcalloc(1, sizeof(struct stage_data));\n \tget_tree_entry(o->object.oid.hash, path,\n-\t\t\te->stages[1].sha, &e->stages[1].mode);\n+\t\t\te->stages[1].oid.hash, &e->stages[1].mode);\n \tget_tree_entry(a->object.oid.hash, path,\n-\t\t\te->stages[2].sha, &e->stages[2].mode);\n+\t\t\te->stages[2].oid.hash, &e->stages[2].mode);\n \tget_tree_entry(b->object.oid.hash, path,\n-\t\t\te->stages[3].sha, &e->stages[3].mode);\n+\t\t\te->stages[3].oid.hash, &e->stages[3].mode);\n \titem = string_list_insert(entries, path);\n \titem->util = e;\n \treturn e;\n@@ -351,7 +349,7 @@ static struct string_list *get_unmerged(void)\n \t\t}\n \t\te = item->util;\n \t\te->stages[ce_stage(ce)].mode = ce->ce_mode;\n-\t\thashcpy(e->stages[ce_stage(ce)].sha, ce->sha1);\n+\t\thashcpy(e->stages[ce_stage(ce)].oid.hash, ce->sha1);\n \t}\n \n \treturn unmerged;\n@@ -574,9 +572,9 @@ static void update_entry(struct stage_data *entry,\n \tentry->stages[1].mode = o->mode;\n \tentry->stages[2].mode = a->mode;\n \tentry->stages[3].mode = b->mode;\n-\thashcpy(entry->stages[1].sha, o->oid.hash);\n-\thashcpy(entry->stages[2].sha, a->oid.hash);\n-\thashcpy(entry->stages[3].sha, b->oid.hash);\n+\toidcpy(&entry->stages[1].oid, &o->oid);\n+\toidcpy(&entry->stages[2].oid, &a->oid);\n+\toidcpy(&entry->stages[3].oid, &b->oid);\n }\n \n static int remove_file(struct merge_options *o, int clean,\n@@ -1111,7 +1109,7 @@ static struct diff_filespec *filespec_from_entry(struct diff_filespec *target,\n \t\t\t\t\t\t struct stage_data *entry,\n \t\t\t\t\t\t int stage)\n {\n-\tunsigned char *sha = entry->stages[stage].sha;\n+\tunsigned char *sha = entry->stages[stage].oid.hash;\n \tunsigned mode = entry->stages[stage].mode;\n \tif (mode == 0 || is_null_sha1(sha))\n \t\treturn NULL;\n@@ -1425,11 +1423,11 @@ static int process_renames(struct merge_options *o,\n \t\t\tremove_file(o, 1, ren1_src,\n \t\t\t\t    renamed_stage == 2 || !was_tracked(ren1_src));\n \n-\t\t\thashcpy(src_other.oid.hash,\n-\t\t\t\tren1->src_entry->stages[other_stage].sha);\n+\t\t\toidcpy(&src_other.oid,\n+\t\t\t       &ren1->src_entry->stages[other_stage].oid);\n \t\t\tsrc_other.mode = ren1->src_entry->stages[other_stage].mode;\n-\t\t\thashcpy(dst_other.oid.hash,\n-\t\t\t\tren1->dst_entry->stages[other_stage].sha);\n+\t\t\toidcpy(&dst_other.oid,\n+\t\t\t       &ren1->dst_entry->stages[other_stage].oid);\n \t\t\tdst_other.mode = ren1->dst_entry->stages[other_stage].mode;\n \t\t\ttry_merge = 0;\n \n@@ -1703,9 +1701,9 @@ static int process_entry(struct merge_options *o,\n \tunsigned o_mode = entry->stages[1].mode;\n \tunsigned a_mode = entry->stages[2].mode;\n \tunsigned b_mode = entry->stages[3].mode;\n-\tunsigned char *o_sha = stage_sha(entry->stages[1].sha, o_mode);\n-\tunsigned char *a_sha = stage_sha(entry->stages[2].sha, a_mode);\n-\tunsigned char *b_sha = stage_sha(entry->stages[3].sha, b_mode);\n+\tunsigned char *o_sha = stage_sha(entry->stages[1].oid.hash, o_mode);\n+\tunsigned char *a_sha = stage_sha(entry->stages[2].oid.hash, a_mode);\n+\tunsigned char *b_sha = stage_sha(entry->stages[3].oid.hash, b_mode);\n \n \tentry->processed = 1;\n \tif (entry->rename_conflict_info) {\n"},{"id":"289591","messageId":"20160618221407.1046188-4-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"[PATCH v2 3/8] Convert struct diff_filespec to struct object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:14:02Z","receivedAt":"2016-06-18T22:14:40Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert struct diff_filespec's sha1 member to use a struct object_id\ncalled \"oid\" instead.  The following Coccinelle semantic patch was used\nto implement this, followed by the transformations in object_id.cocci:\n\n@@\nstruct diff_filespec o;\n@@\n- o.sha1\n+ o.oid.hash\n\n@@\nstruct diff_filespec *p;\n@@\n- p->sha1\n+ p->oid.hash\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/blame.c       |   6 +--\n builtin/fast-export.c |  10 ++---\n builtin/reset.c       |   4 +-\n combine-diff.c        |  10 ++---\n diff.c                |  69 +++++++++++++++++---------------\n diffcore-break.c      |   2 +-\n diffcore-rename.c     |  14 ++++---\n diffcore.h            |   2 +-\n line-log.c            |   2 +-\n merge-recursive.c     | 107 +++++++++++++++++++++++++++-----------------------\n notes-merge.c         |  42 ++++++++++----------\n submodule.c           |   4 +-\n wt-status.c           |   3 +-\n 13 files changed, 147 insertions(+), 128 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 21f42b0b..04bc4e0e 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -599,7 +599,7 @@ static struct origin *find_origin(struct scoreboard *sb,\n \t\t\t    p->status);\n \t\tcase 'M':\n \t\t\tporigin = get_origin(sb, parent, origin->path);\n-\t\t\thashcpy(porigin->blob_sha1, p->one->sha1);\n+\t\t\thashcpy(porigin->blob_sha1, p->one->oid.hash);\n \t\t\tporigin->mode = p->one->mode;\n \t\t\tbreak;\n \t\tcase 'A':\n@@ -645,7 +645,7 @@ static struct origin *find_rename(struct scoreboard *sb,\n \t\tif ((p->status == 'R' || p->status == 'C') &&\n \t\t    !strcmp(p->two->path, origin->path)) {\n \t\t\tporigin = get_origin(sb, parent, p->one->path);\n-\t\t\thashcpy(porigin->blob_sha1, p->one->sha1);\n+\t\t\thashcpy(porigin->blob_sha1, p->one->oid.hash);\n \t\t\tporigin->mode = p->one->mode;\n \t\t\tbreak;\n \t\t}\n@@ -1309,7 +1309,7 @@ static void find_copy_in_parent(struct scoreboard *sb,\n \t\t\t\tcontinue;\n \n \t\t\tnorigin = get_origin(sb, parent, p->one->path);\n-\t\t\thashcpy(norigin->blob_sha1, p->one->sha1);\n+\t\t\thashcpy(norigin->blob_sha1, p->one->oid.hash);\n \t\t\tnorigin->mode = p->one->mode;\n \t\t\tfill_origin_blob(&sb->revs->diffopt, norigin, &file_p);\n \t\t\tif (!file_p.ptr)\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex 8164b581..c0652a7e 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -368,7 +368,7 @@ static void show_filemodify(struct diff_queue_struct *q,\n \t\t\tprint_path(spec->path);\n \t\t\tputchar('\\n');\n \n-\t\t\tif (!hashcmp(ospec->sha1, spec->sha1) &&\n+\t\t\tif (!oidcmp(&ospec->oid, &spec->oid) &&\n \t\t\t    ospec->mode == spec->mode)\n \t\t\t\tbreak;\n \t\t\t/* fallthrough */\n@@ -383,10 +383,10 @@ static void show_filemodify(struct diff_queue_struct *q,\n \t\t\tif (no_data || S_ISGITLINK(spec->mode))\n \t\t\t\tprintf(\"M %06o %s \", spec->mode,\n \t\t\t\t       sha1_to_hex(anonymize ?\n-\t\t\t\t\t\t   anonymize_sha1(spec->sha1) :\n-\t\t\t\t\t\t   spec->sha1));\n+\t\t\t\t\t\t   anonymize_sha1(spec->oid.hash) :\n+\t\t\t\t\t\t   spec->oid.hash));\n \t\t\telse {\n-\t\t\t\tstruct object *object = lookup_object(spec->sha1);\n+\t\t\t\tstruct object *object = lookup_object(spec->oid.hash);\n \t\t\t\tprintf(\"M %06o :%d \", spec->mode,\n \t\t\t\t       get_object_mark(object));\n \t\t\t}\n@@ -572,7 +572,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)\n \t/* Export the referenced blobs, and remember the marks. */\n \tfor (i = 0; i < diff_queued_diff.nr; i++)\n \t\tif (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))\n-\t\t\texport_blob(diff_queued_diff.queue[i]->two->sha1);\n+\t\t\texport_blob(diff_queued_diff.queue[i]->two->oid.hash);\n \n \trefname = commit->util;\n \tif (anonymize) {\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 092c3a53..cce64b53 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -121,7 +121,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,\n \n \tfor (i = 0; i < q->nr; i++) {\n \t\tstruct diff_filespec *one = q->queue[i]->one;\n-\t\tint is_missing = !(one->mode && !is_null_sha1(one->sha1));\n+\t\tint is_missing = !(one->mode && !is_null_oid(&one->oid));\n \t\tstruct cache_entry *ce;\n \n \t\tif (is_missing && !intent_to_add) {\n@@ -129,7 +129,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,\n \t\t\tcontinue;\n \t\t}\n \n-\t\tce = make_cache_entry(one->mode, one->sha1, one->path,\n+\t\tce = make_cache_entry(one->mode, one->oid.hash, one->path,\n \t\t\t\t      0, 0);\n \t\tif (!ce)\n \t\t\tdie(_(\"make_cache_entry failed for path '%s'\"),\ndiff --git a/combine-diff.c b/combine-diff.c\nindex 8f2313d5..3537209c 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -44,9 +44,9 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,\n \t\t\tmemset(p->parent, 0,\n \t\t\t       sizeof(p->parent[0]) * num_parent);\n \n-\t\t\thashcpy(p->oid.hash, q->queue[i]->two->sha1);\n+\t\t\toidcpy(&p->oid, &q->queue[i]->two->oid);\n \t\t\tp->mode = q->queue[i]->two->mode;\n-\t\t\thashcpy(p->parent[n].oid.hash, q->queue[i]->one->sha1);\n+\t\t\toidcpy(&p->parent[n].oid, &q->queue[i]->one->oid);\n \t\t\tp->parent[n].mode = q->queue[i]->one->mode;\n \t\t\tp->parent[n].status = q->queue[i]->status;\n \t\t\t*tail = p;\n@@ -77,7 +77,7 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,\n \t\t\tcontinue;\n \t\t}\n \n-\t\thashcpy(p->parent[n].oid.hash, q->queue[i]->one->sha1);\n+\t\toidcpy(&p->parent[n].oid, &q->queue[i]->one->oid);\n \t\tp->parent[n].mode = q->queue[i]->one->mode;\n \t\tp->parent[n].status = q->queue[i]->status;\n \n@@ -1268,7 +1268,7 @@ static struct diff_filepair *combined_pair(struct combine_diff_path *p,\n \tfor (i = 0; i < num_parent; i++) {\n \t\tpair->one[i].path = p->path;\n \t\tpair->one[i].mode = p->parent[i].mode;\n-\t\thashcpy(pair->one[i].sha1, p->parent[i].oid.hash);\n+\t\toidcpy(&pair->one[i].oid, &p->parent[i].oid);\n \t\tpair->one[i].sha1_valid = !is_null_oid(&p->parent[i].oid);\n \t\tpair->one[i].has_more_entries = 1;\n \t}\n@@ -1276,7 +1276,7 @@ static struct diff_filepair *combined_pair(struct combine_diff_path *p,\n \n \tpair->two->path = p->path;\n \tpair->two->mode = p->mode;\n-\thashcpy(pair->two->sha1, p->oid.hash);\n+\toidcpy(&pair->two->oid, &p->oid);\n \tpair->two->sha1_valid = !is_null_oid(&p->oid);\n \treturn pair;\n }\ndiff --git a/diff.c b/diff.c\nindex fa78fc18..5a6d8654 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1934,7 +1934,7 @@ static void show_dirstat(struct diff_options *options)\n \t\tname = p->two->path ? p->two->path : p->one->path;\n \n \t\tif (p->one->sha1_valid && p->two->sha1_valid)\n-\t\t\tcontent_changed = hashcmp(p->one->sha1, p->two->sha1);\n+\t\t\tcontent_changed = oidcmp(&p->one->oid, &p->two->oid);\n \t\telse\n \t\t\tcontent_changed = 1;\n \n@@ -2306,7 +2306,8 @@ static void builtin_diff(const char *name_a,\n \t\tconst char *add = diff_get_color_opt(o, DIFF_FILE_NEW);\n \t\tshow_submodule_summary(o->file, one->path ? one->path : two->path,\n \t\t\t\tline_prefix,\n-\t\t\t\tone->sha1, two->sha1, two->dirty_submodule,\n+\t\t\t\tone->oid.hash, two->oid.hash,\n+\t\t\t\ttwo->dirty_submodule,\n \t\t\t\tmeta, del, add, reset);\n \t\treturn;\n \t}\n@@ -2384,7 +2385,7 @@ static void builtin_diff(const char *name_a,\n \t\tif (!one->data && !two->data &&\n \t\t    S_ISREG(one->mode) && S_ISREG(two->mode) &&\n \t\t    !DIFF_OPT_TST(o, BINARY)) {\n-\t\t\tif (!hashcmp(one->sha1, two->sha1)) {\n+\t\t\tif (!oidcmp(&one->oid, &two->oid)) {\n \t\t\t\tif (must_show_header)\n \t\t\t\t\tfprintf(o->file, \"%s\", header.buf);\n \t\t\t\tgoto free_ab_and_return;\n@@ -2505,7 +2506,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,\n \t\treturn;\n \t}\n \n-\tsame_contents = !hashcmp(one->sha1, two->sha1);\n+\tsame_contents = !oidcmp(&one->oid, &two->oid);\n \n \tif (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {\n \t\tdata->is_binary = 1;\n@@ -2638,7 +2639,7 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,\n {\n \tif (mode) {\n \t\tspec->mode = canon_mode(mode);\n-\t\thashcpy(spec->sha1, sha1);\n+\t\thashcpy(spec->oid.hash, sha1);\n \t\tspec->sha1_valid = sha1_valid;\n \t}\n }\n@@ -2721,7 +2722,8 @@ static int diff_populate_gitlink(struct diff_filespec *s, int size_only)\n \tif (s->dirty_submodule)\n \t\tdirty = \"-dirty\";\n \n-\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\", sha1_to_hex(s->sha1), dirty);\n+\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\",\n+\t\t    oid_to_hex(&s->oid), dirty);\n \ts->size = buf.len;\n \tif (size_only) {\n \t\ts->data = NULL;\n@@ -2765,7 +2767,7 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)\n \t\treturn diff_populate_gitlink(s, size_only);\n \n \tif (!s->sha1_valid ||\n-\t    reuse_worktree_file(s->path, s->sha1, 0)) {\n+\t    reuse_worktree_file(s->path, s->oid.hash, 0)) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n \t\tstruct stat st;\n \t\tint fd;\n@@ -2822,9 +2824,10 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)\n \telse {\n \t\tenum object_type type;\n \t\tif (size_only || (flags & CHECK_BINARY)) {\n-\t\t\ttype = sha1_object_info(s->sha1, &s->size);\n+\t\t\ttype = sha1_object_info(s->oid.hash, &s->size);\n \t\t\tif (type < 0)\n-\t\t\t\tdie(\"unable to read %s\", sha1_to_hex(s->sha1));\n+\t\t\t\tdie(\"unable to read %s\",\n+\t\t\t\t    oid_to_hex(&s->oid));\n \t\t\tif (size_only)\n \t\t\t\treturn 0;\n \t\t\tif (s->size > big_file_threshold && s->is_binary == -1) {\n@@ -2832,9 +2835,9 @@ int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)\n \t\t\t\treturn 0;\n \t\t\t}\n \t\t}\n-\t\ts->data = read_sha1_file(s->sha1, &type, &s->size);\n+\t\ts->data = read_sha1_file(s->oid.hash, &type, &s->size);\n \t\tif (!s->data)\n-\t\t\tdie(\"unable to read %s\", sha1_to_hex(s->sha1));\n+\t\t\tdie(\"unable to read %s\", oid_to_hex(&s->oid));\n \t\ts->should_free = 1;\n \t}\n \treturn 0;\n@@ -2913,7 +2916,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n \n \tif (!S_ISGITLINK(one->mode) &&\n \t    (!one->sha1_valid ||\n-\t     reuse_worktree_file(name, one->sha1, 1))) {\n+\t     reuse_worktree_file(name, one->oid.hash, 1))) {\n \t\tstruct stat st;\n \t\tif (lstat(name, &st) < 0) {\n \t\t\tif (errno == ENOENT)\n@@ -2926,7 +2929,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n \t\t\t\tdie_errno(\"readlink(%s)\", name);\n \t\t\tprep_temp_blob(name, temp, sb.buf, sb.len,\n \t\t\t\t       (one->sha1_valid ?\n-\t\t\t\t\tone->sha1 : null_sha1),\n+\t\t\t\t\tone->oid.hash : null_sha1),\n \t\t\t\t       (one->sha1_valid ?\n \t\t\t\t\tone->mode : S_IFLNK));\n \t\t\tstrbuf_release(&sb);\n@@ -2937,7 +2940,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n \t\t\tif (!one->sha1_valid)\n \t\t\t\tsha1_to_hex_r(temp->hex, null_sha1);\n \t\t\telse\n-\t\t\t\tsha1_to_hex_r(temp->hex, one->sha1);\n+\t\t\t\tsha1_to_hex_r(temp->hex, one->oid.hash);\n \t\t\t/* Even though we may sometimes borrow the\n \t\t\t * contents from the work tree, we always want\n \t\t\t * one->mode.  mode is trustworthy even when\n@@ -2952,7 +2955,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n \t\tif (diff_populate_filespec(one, 0))\n \t\t\tdie(\"cannot read data blob for %s\", one->path);\n \t\tprep_temp_blob(name, temp, one->data, one->size,\n-\t\t\t       one->sha1, one->mode);\n+\t\t\t       one->oid.hash, one->mode);\n \t}\n \treturn temp;\n }\n@@ -3065,7 +3068,7 @@ static void fill_metainfo(struct strbuf *msg,\n \tdefault:\n \t\t*must_show_header = 0;\n \t}\n-\tif (one && two && hashcmp(one->sha1, two->sha1)) {\n+\tif (one && two && oidcmp(&one->oid, &two->oid)) {\n \t\tint abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;\n \n \t\tif (DIFF_OPT_TST(o, BINARY)) {\n@@ -3075,8 +3078,8 @@ static void fill_metainfo(struct strbuf *msg,\n \t\t\t\tabbrev = 40;\n \t\t}\n \t\tstrbuf_addf(msg, \"%s%sindex %s..\", line_prefix, set,\n-\t\t\t    find_unique_abbrev(one->sha1, abbrev));\n-\t\tstrbuf_addstr(msg, find_unique_abbrev(two->sha1, abbrev));\n+\t\t\t    find_unique_abbrev(one->oid.hash, abbrev));\n+\t\tstrbuf_addstr(msg, find_unique_abbrev(two->oid.hash, abbrev));\n \t\tif (one->mode == two->mode)\n \t\t\tstrbuf_addf(msg, \" %06o\", one->mode);\n \t\tstrbuf_addf(msg, \"%s\\n\", reset);\n@@ -3134,17 +3137,17 @@ static void diff_fill_sha1_info(struct diff_filespec *one)\n \t\tif (!one->sha1_valid) {\n \t\t\tstruct stat st;\n \t\t\tif (one->is_stdin) {\n-\t\t\t\thashcpy(one->sha1, null_sha1);\n+\t\t\t\thashcpy(one->oid.hash, null_sha1);\n \t\t\t\treturn;\n \t\t\t}\n \t\t\tif (lstat(one->path, &st) < 0)\n \t\t\t\tdie_errno(\"stat '%s'\", one->path);\n-\t\t\tif (index_path(one->sha1, one->path, &st, 0))\n+\t\t\tif (index_path(one->oid.hash, one->path, &st, 0))\n \t\t\t\tdie(\"cannot hash %s\", one->path);\n \t\t}\n \t}\n \telse\n-\t\thashclr(one->sha1);\n+\t\toidclr(&one->oid);\n }\n \n static void strip_prefix(int prefix_length, const char **namep, const char **otherp)\n@@ -4118,8 +4121,9 @@ static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt)\n \tfprintf(opt->file, \"%s\", diff_line_prefix(opt));\n \tif (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) {\n \t\tfprintf(opt->file, \":%06o %06o %s \", p->one->mode, p->two->mode,\n-\t\t\tdiff_unique_abbrev(p->one->sha1, opt->abbrev));\n-\t\tfprintf(opt->file, \"%s \", diff_unique_abbrev(p->two->sha1, opt->abbrev));\n+\t\t\tdiff_unique_abbrev(p->one->oid.hash, opt->abbrev));\n+\t\tfprintf(opt->file, \"%s \",\n+\t\t\tdiff_unique_abbrev(p->two->oid.hash, opt->abbrev));\n \t}\n \tif (p->score) {\n \t\tfprintf(opt->file, \"%c%03d%c\", p->status, similarity_index(p),\n@@ -4169,7 +4173,7 @@ int diff_unmodified_pair(struct diff_filepair *p)\n \t * dealing with a change.\n \t */\n \tif (one->sha1_valid && two->sha1_valid &&\n-\t    !hashcmp(one->sha1, two->sha1) &&\n+\t    !oidcmp(&one->oid, &two->oid) &&\n \t    !one->dirty_submodule && !two->dirty_submodule)\n \t\treturn 1; /* no change */\n \tif (!one->sha1_valid && !two->sha1_valid)\n@@ -4233,7 +4237,7 @@ void diff_debug_filespec(struct diff_filespec *s, int x, const char *one)\n \t\ts->path,\n \t\tDIFF_FILE_VALID(s) ? \"valid\" : \"invalid\",\n \t\ts->mode,\n-\t\ts->sha1_valid ? sha1_to_hex(s->sha1) : \"\");\n+\t\ts->sha1_valid ? oid_to_hex(&s->oid) : \"\");\n \tfprintf(stderr, \"queue[%d] %s size %lu\\n\",\n \t\tx, one ? one : \"\",\n \t\ts->size);\n@@ -4303,11 +4307,11 @@ static void diff_resolve_rename_copy(void)\n \t\t\telse\n \t\t\t\tp->status = DIFF_STATUS_RENAMED;\n \t\t}\n-\t\telse if (hashcmp(p->one->sha1, p->two->sha1) ||\n+\t\telse if (oidcmp(&p->one->oid, &p->two->oid) ||\n \t\t\t p->one->mode != p->two->mode ||\n \t\t\t p->one->dirty_submodule ||\n \t\t\t p->two->dirty_submodule ||\n-\t\t\t is_null_sha1(p->one->sha1))\n+\t\t\t is_null_oid(&p->one->oid))\n \t\t\tp->status = DIFF_STATUS_MODIFIED;\n \t\telse {\n \t\t\t/* This is a \"no-change\" entry and should not\n@@ -4523,8 +4527,10 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)\n \n \t\tif (diff_filespec_is_binary(p->one) ||\n \t\t    diff_filespec_is_binary(p->two)) {\n-\t\t\tgit_SHA1_Update(&ctx, sha1_to_hex(p->one->sha1), 40);\n-\t\t\tgit_SHA1_Update(&ctx, sha1_to_hex(p->two->sha1), 40);\n+\t\t\tgit_SHA1_Update(&ctx, oid_to_hex(&p->one->oid),\n+\t\t\t\t\t40);\n+\t\t\tgit_SHA1_Update(&ctx, oid_to_hex(&p->two->oid),\n+\t\t\t\t\t40);\n \t\t\tcontinue;\n \t\t}\n \n@@ -5113,7 +5119,8 @@ size_t fill_textconv(struct userdiff_driver *driver,\n \t\tdie(\"BUG: fill_textconv called with non-textconv driver\");\n \n \tif (driver->textconv_cache && df->sha1_valid) {\n-\t\t*outbuf = notes_cache_get(driver->textconv_cache, df->sha1,\n+\t\t*outbuf = notes_cache_get(driver->textconv_cache,\n+\t\t\t\t\t  df->oid.hash,\n \t\t\t\t\t  &size);\n \t\tif (*outbuf)\n \t\t\treturn size;\n@@ -5125,7 +5132,7 @@ size_t fill_textconv(struct userdiff_driver *driver,\n \n \tif (driver->textconv_cache && df->sha1_valid) {\n \t\t/* ignore errors, as we might be in a readonly repository */\n-\t\tnotes_cache_put(driver->textconv_cache, df->sha1, *outbuf,\n+\t\tnotes_cache_put(driver->textconv_cache, df->oid.hash, *outbuf,\n \t\t\t\tsize);\n \t\t/*\n \t\t * we could save up changes and flush them all at the end,\ndiff --git a/diffcore-break.c b/diffcore-break.c\nindex 5473493e..a3e79608 100644\n--- a/diffcore-break.c\n+++ b/diffcore-break.c\n@@ -58,7 +58,7 @@ static int should_break(struct diff_filespec *src,\n \t}\n \n \tif (src->sha1_valid && dst->sha1_valid &&\n-\t    !hashcmp(src->sha1, dst->sha1))\n+\t    !oidcmp(&src->oid, &dst->oid))\n \t\treturn 0; /* they are the same */\n \n \tif (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))\ndiff --git a/diffcore-rename.c b/diffcore-rename.c\nindex 7f03eb5a..22b239a4 100644\n--- a/diffcore-rename.c\n+++ b/diffcore-rename.c\n@@ -60,7 +60,8 @@ static int add_rename_dst(struct diff_filespec *two)\n \t\tmemmove(rename_dst + first + 1, rename_dst + first,\n \t\t\t(rename_dst_nr - first - 1) * sizeof(*rename_dst));\n \trename_dst[first].two = alloc_filespec(two->path);\n-\tfill_filespec(rename_dst[first].two, two->sha1, two->sha1_valid, two->mode);\n+\tfill_filespec(rename_dst[first].two, two->oid.hash, two->sha1_valid,\n+\t\t      two->mode);\n \trename_dst[first].pair = NULL;\n \treturn 0;\n }\n@@ -263,9 +264,10 @@ static unsigned int hash_filespec(struct diff_filespec *filespec)\n \tif (!filespec->sha1_valid) {\n \t\tif (diff_populate_filespec(filespec, 0))\n \t\t\treturn 0;\n-\t\thash_sha1_file(filespec->data, filespec->size, \"blob\", filespec->sha1);\n+\t\thash_sha1_file(filespec->data, filespec->size, \"blob\",\n+\t\t\t       filespec->oid.hash);\n \t}\n-\treturn sha1hash(filespec->sha1);\n+\treturn sha1hash(filespec->oid.hash);\n }\n \n static int find_identical_files(struct hashmap *srcs,\n@@ -287,7 +289,7 @@ static int find_identical_files(struct hashmap *srcs,\n \t\tstruct diff_filespec *source = p->filespec;\n \n \t\t/* False hash collision? */\n-\t\tif (hashcmp(source->sha1, target->sha1))\n+\t\tif (oidcmp(&source->oid, &target->oid))\n \t\t\tcontinue;\n \t\t/* Non-regular files? If so, the modes must match! */\n \t\tif (!S_ISREG(source->mode) || !S_ISREG(target->mode)) {\n@@ -466,7 +468,7 @@ void diffcore_rename(struct diff_options *options)\n \t\t\t\t strcmp(options->single_follow, p->two->path))\n \t\t\t\tcontinue; /* not interested */\n \t\t\telse if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&\n-\t\t\t\t is_empty_blob_sha1(p->two->sha1))\n+\t\t\t\t is_empty_blob_sha1(p->two->oid.hash))\n \t\t\t\tcontinue;\n \t\t\telse if (add_rename_dst(p->two) < 0) {\n \t\t\t\twarning(\"skipping rename detection, detected\"\n@@ -476,7 +478,7 @@ void diffcore_rename(struct diff_options *options)\n \t\t\t}\n \t\t}\n \t\telse if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&\n-\t\t\t is_empty_blob_sha1(p->one->sha1))\n+\t\t\t is_empty_blob_sha1(p->one->oid.hash))\n \t\t\tcontinue;\n \t\telse if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) {\n \t\t\t/*\ndiff --git a/diffcore.h b/diffcore.h\nindex 33ea2de3..c40e5b6c 100644\n--- a/diffcore.h\n+++ b/diffcore.h\n@@ -25,7 +25,7 @@\n struct userdiff_driver;\n \n struct diff_filespec {\n-\tunsigned char sha1[20];\n+\tstruct object_id oid;\n \tchar *path;\n \tvoid *data;\n \tvoid *cnt_data;\ndiff --git a/line-log.c b/line-log.c\nindex bbe31ed6..02938639 100644\n--- a/line-log.c\n+++ b/line-log.c\n@@ -520,7 +520,7 @@ static void fill_line_ends(struct diff_filespec *spec, long *lines,\n \tchar *data = NULL;\n \n \tif (diff_populate_filespec(spec, 0))\n-\t\tdie(\"Cannot read blob %s\", sha1_to_hex(spec->sha1));\n+\t\tdie(\"Cannot read blob %s\", oid_to_hex(&spec->oid));\n \n \tALLOC_ARRAY(ends, size);\n \tends[cur++] = 0;\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 65cb5d6c..1e802097 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -134,11 +134,13 @@ static inline void setup_rename_conflict_info(enum rename_type rename_type,\n \t\tint ostage2 = ostage1 ^ 1;\n \n \t\tci->ren1_other.path = pair1->one->path;\n-\t\thashcpy(ci->ren1_other.sha1, src_entry1->stages[ostage1].sha);\n+\t\thashcpy(ci->ren1_other.oid.hash,\n+\t\t\tsrc_entry1->stages[ostage1].sha);\n \t\tci->ren1_other.mode = src_entry1->stages[ostage1].mode;\n \n \t\tci->ren2_other.path = pair2->one->path;\n-\t\thashcpy(ci->ren2_other.sha1, src_entry2->stages[ostage2].sha);\n+\t\thashcpy(ci->ren2_other.oid.hash,\n+\t\t\tsrc_entry2->stages[ostage2].sha);\n \t\tci->ren2_other.mode = src_entry2->stages[ostage2].mode;\n \t}\n }\n@@ -552,13 +554,13 @@ static int update_stages(const char *path, const struct diff_filespec *o,\n \t\tif (remove_file_from_cache(path))\n \t\t\treturn -1;\n \tif (o)\n-\t\tif (add_cacheinfo(o->mode, o->sha1, path, 1, 0, options))\n+\t\tif (add_cacheinfo(o->mode, o->oid.hash, path, 1, 0, options))\n \t\t\treturn -1;\n \tif (a)\n-\t\tif (add_cacheinfo(a->mode, a->sha1, path, 2, 0, options))\n+\t\tif (add_cacheinfo(a->mode, a->oid.hash, path, 2, 0, options))\n \t\t\treturn -1;\n \tif (b)\n-\t\tif (add_cacheinfo(b->mode, b->sha1, path, 3, 0, options))\n+\t\tif (add_cacheinfo(b->mode, b->oid.hash, path, 3, 0, options))\n \t\t\treturn -1;\n \treturn 0;\n }\n@@ -572,9 +574,9 @@ static void update_entry(struct stage_data *entry,\n \tentry->stages[1].mode = o->mode;\n \tentry->stages[2].mode = a->mode;\n \tentry->stages[3].mode = b->mode;\n-\thashcpy(entry->stages[1].sha, o->sha1);\n-\thashcpy(entry->stages[2].sha, a->sha1);\n-\thashcpy(entry->stages[3].sha, b->sha1);\n+\thashcpy(entry->stages[1].sha, o->oid.hash);\n+\thashcpy(entry->stages[2].sha, a->oid.hash);\n+\thashcpy(entry->stages[3].sha, b->oid.hash);\n }\n \n static int remove_file(struct merge_options *o, int clean,\n@@ -871,9 +873,9 @@ static int merge_3way(struct merge_options *o,\n \t\tname2 = mkpathdup(\"%s\", branch2);\n \t}\n \n-\tread_mmblob(&orig, one->sha1);\n-\tread_mmblob(&src1, a->sha1);\n-\tread_mmblob(&src2, b->sha1);\n+\tread_mmblob(&orig, one->oid.hash);\n+\tread_mmblob(&src1, a->oid.hash);\n+\tread_mmblob(&src2, b->oid.hash);\n \n \tmerge_status = ll_merge(result_buf, a->path, &orig, base_name,\n \t\t\t\t&src1, name1, &src2, name2, &ll_opts);\n@@ -902,13 +904,13 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\tresult.clean = 0;\n \t\tif (S_ISREG(a->mode)) {\n \t\t\tresult.mode = a->mode;\n-\t\t\thashcpy(result.sha, a->sha1);\n+\t\t\thashcpy(result.sha, a->oid.hash);\n \t\t} else {\n \t\t\tresult.mode = b->mode;\n-\t\t\thashcpy(result.sha, b->sha1);\n+\t\t\thashcpy(result.sha, b->oid.hash);\n \t\t}\n \t} else {\n-\t\tif (!sha_eq(a->sha1, one->sha1) && !sha_eq(b->sha1, one->sha1))\n+\t\tif (!sha_eq(a->oid.hash, one->oid.hash) && !sha_eq(b->oid.hash, one->oid.hash))\n \t\t\tresult.merge = 1;\n \n \t\t/*\n@@ -924,10 +926,10 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\t\t}\n \t\t}\n \n-\t\tif (sha_eq(a->sha1, b->sha1) || sha_eq(a->sha1, one->sha1))\n-\t\t\thashcpy(result.sha, b->sha1);\n-\t\telse if (sha_eq(b->sha1, one->sha1))\n-\t\t\thashcpy(result.sha, a->sha1);\n+\t\tif (sha_eq(a->oid.hash, b->oid.hash) || sha_eq(a->oid.hash, one->oid.hash))\n+\t\t\thashcpy(result.sha, b->oid.hash);\n+\t\telse if (sha_eq(b->oid.hash, one->oid.hash))\n+\t\t\thashcpy(result.sha, a->oid.hash);\n \t\telse if (S_ISREG(a->mode)) {\n \t\t\tmmbuffer_t result_buf;\n \t\t\tint merge_status;\n@@ -947,13 +949,15 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n \t\t\tresult.clean = (merge_status == 0);\n \t\t} else if (S_ISGITLINK(a->mode)) {\n \t\t\tresult.clean = merge_submodule(result.sha,\n-\t\t\t\t\t\t       one->path, one->sha1,\n-\t\t\t\t\t\t       a->sha1, b->sha1,\n+\t\t\t\t\t\t       one->path,\n+\t\t\t\t\t\t       one->oid.hash,\n+\t\t\t\t\t\t       a->oid.hash,\n+\t\t\t\t\t\t       b->oid.hash,\n \t\t\t\t\t\t       !o->call_depth);\n \t\t} else if (S_ISLNK(a->mode)) {\n-\t\t\thashcpy(result.sha, a->sha1);\n+\t\t\thashcpy(result.sha, a->oid.hash);\n \n-\t\t\tif (!sha_eq(a->sha1, b->sha1))\n+\t\t\tif (!sha_eq(a->oid.hash, b->oid.hash))\n \t\t\t\tresult.clean = 0;\n \t\t} else {\n \t\t\tdie(_(\"unsupported object type in the tree\"));\n@@ -1000,11 +1004,11 @@ static struct merge_file_info merge_file_one(struct merge_options *o,\n \tstruct diff_filespec one, a, b;\n \n \tone.path = a.path = b.path = (char *)path;\n-\thashcpy(one.sha1, o_sha);\n+\thashcpy(one.oid.hash, o_sha);\n \tone.mode = o_mode;\n-\thashcpy(a.sha1, a_sha);\n+\thashcpy(a.oid.hash, a_sha);\n \ta.mode = a_mode;\n-\thashcpy(b.sha1, b_sha);\n+\thashcpy(b.oid.hash, b_sha);\n \tb.mode = b_mode;\n \treturn merge_file_1(o, &one, &a, &b, branch1, branch2);\n }\n@@ -1079,16 +1083,16 @@ static void conflict_rename_delete(struct merge_options *o,\n \tint b_mode = 0;\n \n \tif (rename_branch == o->branch1) {\n-\t\ta_sha = dest->sha1;\n+\t\ta_sha = dest->oid.hash;\n \t\ta_mode = dest->mode;\n \t} else {\n-\t\tb_sha = dest->sha1;\n+\t\tb_sha = dest->oid.hash;\n \t\tb_mode = dest->mode;\n \t}\n \n \thandle_change_delete(o,\n \t\t\t     o->call_depth ? orig->path : dest->path,\n-\t\t\t     orig->sha1, orig->mode,\n+\t\t\t     orig->oid.hash, orig->mode,\n \t\t\t     a_sha, a_mode,\n \t\t\t     b_sha, b_mode,\n \t\t\t     _(\"rename\"), _(\"renamed\"));\n@@ -1111,7 +1115,7 @@ static struct diff_filespec *filespec_from_entry(struct diff_filespec *target,\n \tunsigned mode = entry->stages[stage].mode;\n \tif (mode == 0 || is_null_sha1(sha))\n \t\treturn NULL;\n-\thashcpy(target->sha1, sha);\n+\thashcpy(target->oid.hash, sha);\n \ttarget->mode = mode;\n \treturn target;\n }\n@@ -1140,7 +1144,7 @@ static void handle_file(struct merge_options *o,\n \tadd = filespec_from_entry(&other, dst_entry, stage ^ 1);\n \tif (add) {\n \t\tchar *add_name = unique_path(o, rename->path, other_branch);\n-\t\tupdate_file(o, 0, add->sha1, add->mode, add_name);\n+\t\tupdate_file(o, 0, add->oid.hash, add->mode, add_name);\n \n \t\tremove_file(o, 0, rename->path, 0);\n \t\tdst_name = unique_path(o, rename->path, cur_branch);\n@@ -1151,7 +1155,7 @@ static void handle_file(struct merge_options *o,\n \t\t\t       rename->path, other_branch, dst_name);\n \t\t}\n \t}\n-\tupdate_file(o, 0, rename->sha1, rename->mode, dst_name);\n+\tupdate_file(o, 0, rename->oid.hash, rename->mode, dst_name);\n \tif (stage == 2)\n \t\tupdate_stages(rename->path, NULL, rename, add);\n \telse\n@@ -1180,9 +1184,9 @@ static void conflict_rename_rename_1to2(struct merge_options *o,\n \t\tstruct diff_filespec other;\n \t\tstruct diff_filespec *add;\n \t\tmfi = merge_file_one(o, one->path,\n-\t\t\t\t one->sha1, one->mode,\n-\t\t\t\t a->sha1, a->mode,\n-\t\t\t\t b->sha1, b->mode,\n+\t\t\t\t one->oid.hash, one->mode,\n+\t\t\t\t a->oid.hash, a->mode,\n+\t\t\t\t b->oid.hash, b->mode,\n \t\t\t\t ci->branch1, ci->branch2);\n \t\t/*\n \t\t * FIXME: For rename/add-source conflicts (if we could detect\n@@ -1202,12 +1206,12 @@ static void conflict_rename_rename_1to2(struct merge_options *o,\n \t\t */\n \t\tadd = filespec_from_entry(&other, ci->dst_entry1, 2 ^ 1);\n \t\tif (add)\n-\t\t\tupdate_file(o, 0, add->sha1, add->mode, a->path);\n+\t\t\tupdate_file(o, 0, add->oid.hash, add->mode, a->path);\n \t\telse\n \t\t\tremove_file_from_cache(a->path);\n \t\tadd = filespec_from_entry(&other, ci->dst_entry2, 3 ^ 1);\n \t\tif (add)\n-\t\t\tupdate_file(o, 0, add->sha1, add->mode, b->path);\n+\t\t\tupdate_file(o, 0, add->oid.hash, add->mode, b->path);\n \t\telse\n \t\t\tremove_file_from_cache(b->path);\n \t} else {\n@@ -1421,13 +1425,15 @@ static int process_renames(struct merge_options *o,\n \t\t\tremove_file(o, 1, ren1_src,\n \t\t\t\t    renamed_stage == 2 || !was_tracked(ren1_src));\n \n-\t\t\thashcpy(src_other.sha1, ren1->src_entry->stages[other_stage].sha);\n+\t\t\thashcpy(src_other.oid.hash,\n+\t\t\t\tren1->src_entry->stages[other_stage].sha);\n \t\t\tsrc_other.mode = ren1->src_entry->stages[other_stage].mode;\n-\t\t\thashcpy(dst_other.sha1, ren1->dst_entry->stages[other_stage].sha);\n+\t\t\thashcpy(dst_other.oid.hash,\n+\t\t\t\tren1->dst_entry->stages[other_stage].sha);\n \t\t\tdst_other.mode = ren1->dst_entry->stages[other_stage].mode;\n \t\t\ttry_merge = 0;\n \n-\t\t\tif (sha_eq(src_other.sha1, null_sha1)) {\n+\t\t\tif (sha_eq(src_other.oid.hash, null_sha1)) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_DELETE,\n \t\t\t\t\t\t\t   ren1->pair,\n \t\t\t\t\t\t\t   NULL,\n@@ -1439,7 +1445,7 @@ static int process_renames(struct merge_options *o,\n \t\t\t\t\t\t\t   NULL,\n \t\t\t\t\t\t\t   NULL);\n \t\t\t} else if ((dst_other.mode == ren1->pair->two->mode) &&\n-\t\t\t\t   sha_eq(dst_other.sha1, ren1->pair->two->sha1)) {\n+\t\t\t\t   sha_eq(dst_other.oid.hash, ren1->pair->two->oid.hash)) {\n \t\t\t\t/*\n \t\t\t\t * Added file on the other side identical to\n \t\t\t\t * the file being renamed: clean merge.\n@@ -1449,12 +1455,12 @@ static int process_renames(struct merge_options *o,\n \t\t\t\t * update_file().\n \t\t\t\t */\n \t\t\t\tupdate_file_flags(o,\n-\t\t\t\t\t\t  ren1->pair->two->sha1,\n+\t\t\t\t\t\t  ren1->pair->two->oid.hash,\n \t\t\t\t\t\t  ren1->pair->two->mode,\n \t\t\t\t\t\t  ren1_dst,\n \t\t\t\t\t\t  1, /* update_cache */\n \t\t\t\t\t\t  0  /* update_wd    */);\n-\t\t\t} else if (!sha_eq(dst_other.sha1, null_sha1)) {\n+\t\t\t} else if (!sha_eq(dst_other.oid.hash, null_sha1)) {\n \t\t\t\tclean_merge = 0;\n \t\t\t\ttry_merge = 1;\n \t\t\t\toutput(o, 1, _(\"CONFLICT (rename/add): Rename %s->%s in %s. \"\n@@ -1464,8 +1470,10 @@ static int process_renames(struct merge_options *o,\n \t\t\t\tif (o->call_depth) {\n \t\t\t\t\tstruct merge_file_info mfi;\n \t\t\t\t\tmfi = merge_file_one(o, ren1_dst, null_sha1, 0,\n-\t\t\t\t\t\t\t ren1->pair->two->sha1, ren1->pair->two->mode,\n-\t\t\t\t\t\t\t dst_other.sha1, dst_other.mode,\n+\t\t\t\t\t\t\t ren1->pair->two->oid.hash,\n+\t\t\t\t\t\t\t ren1->pair->two->mode,\n+\t\t\t\t\t\t\t dst_other.oid.hash,\n+\t\t\t\t\t\t\t dst_other.mode,\n \t\t\t\t\t\t\t branch1, branch2);\n \t\t\t\t\toutput(o, 1, _(\"Adding merged %s\"), ren1_dst);\n \t\t\t\t\tupdate_file(o, 0, mfi.sha, mfi.mode, ren1_dst);\n@@ -1473,7 +1481,8 @@ static int process_renames(struct merge_options *o,\n \t\t\t\t} else {\n \t\t\t\t\tchar *new_path = unique_path(o, ren1_dst, branch2);\n \t\t\t\t\toutput(o, 1, _(\"Adding as %s instead\"), new_path);\n-\t\t\t\t\tupdate_file(o, 0, dst_other.sha1, dst_other.mode, new_path);\n+\t\t\t\t\tupdate_file(o, 0, dst_other.oid.hash,\n+\t\t\t\t\t\t    dst_other.mode, new_path);\n \t\t\t\t\tfree(new_path);\n \t\t\t\t}\n \t\t\t} else\n@@ -1599,11 +1608,11 @@ static int merge_content(struct merge_options *o,\n \t\to_sha = (unsigned char *)null_sha1;\n \t}\n \tone.path = a.path = b.path = (char *)path;\n-\thashcpy(one.sha1, o_sha);\n+\thashcpy(one.oid.hash, o_sha);\n \tone.mode = o_mode;\n-\thashcpy(a.sha1, a_sha);\n+\thashcpy(a.oid.hash, a_sha);\n \ta.mode = a_mode;\n-\thashcpy(b.sha1, b_sha);\n+\thashcpy(b.oid.hash, b_sha);\n \tb.mode = b_mode;\n \n \tif (rename_conflict_info) {\n@@ -1664,7 +1673,7 @@ static int merge_content(struct merge_options *o,\n \t\t\telse {\n \t\t\t\tint file_from_stage2 = was_tracked(path);\n \t\t\t\tstruct diff_filespec merged;\n-\t\t\t\thashcpy(merged.sha1, mfi.sha);\n+\t\t\t\thashcpy(merged.oid.hash, mfi.sha);\n \t\t\t\tmerged.mode = mfi.mode;\n \n \t\t\t\tupdate_stages(path, NULL,\ndiff --git a/notes-merge.c b/notes-merge.c\nindex 34bfac0c..62c23d8a 100644\n--- a/notes-merge.c\n+++ b/notes-merge.c\n@@ -41,14 +41,14 @@ static int verify_notes_filepair(struct diff_filepair *p, unsigned char *sha1)\n \tswitch (p->status) {\n \tcase DIFF_STATUS_MODIFIED:\n \t\tassert(p->one->mode == p->two->mode);\n-\t\tassert(!is_null_sha1(p->one->sha1));\n-\t\tassert(!is_null_sha1(p->two->sha1));\n+\t\tassert(!is_null_oid(&p->one->oid));\n+\t\tassert(!is_null_oid(&p->two->oid));\n \t\tbreak;\n \tcase DIFF_STATUS_ADDED:\n-\t\tassert(is_null_sha1(p->one->sha1));\n+\t\tassert(is_null_oid(&p->one->oid));\n \t\tbreak;\n \tcase DIFF_STATUS_DELETED:\n-\t\tassert(is_null_sha1(p->two->sha1));\n+\t\tassert(is_null_oid(&p->two->oid));\n \t\tbreak;\n \tdefault:\n \t\treturn -1;\n@@ -142,27 +142,27 @@ static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o,\n \t\tif (verify_notes_filepair(p, obj)) {\n \t\t\ttrace_printf(\"\\t\\tCannot merge entry '%s' (%c): \"\n \t\t\t       \"%.7s -> %.7s. Skipping!\\n\", p->one->path,\n-\t\t\t       p->status, sha1_to_hex(p->one->sha1),\n-\t\t\t       sha1_to_hex(p->two->sha1));\n+\t\t\t       p->status, oid_to_hex(&p->one->oid),\n+\t\t\t       oid_to_hex(&p->two->oid));\n \t\t\tcontinue;\n \t\t}\n \t\tmp = find_notes_merge_pair_pos(changes, len, obj, 1, &occupied);\n \t\tif (occupied) {\n \t\t\t/* We've found an addition/deletion pair */\n \t\t\tassert(!hashcmp(mp->obj, obj));\n-\t\t\tif (is_null_sha1(p->one->sha1)) { /* addition */\n+\t\t\tif (is_null_oid(&p->one->oid)) { /* addition */\n \t\t\t\tassert(is_null_sha1(mp->remote));\n-\t\t\t\thashcpy(mp->remote, p->two->sha1);\n-\t\t\t} else if (is_null_sha1(p->two->sha1)) { /* deletion */\n+\t\t\t\thashcpy(mp->remote, p->two->oid.hash);\n+\t\t\t} else if (is_null_oid(&p->two->oid)) { /* deletion */\n \t\t\t\tassert(is_null_sha1(mp->base));\n-\t\t\t\thashcpy(mp->base, p->one->sha1);\n+\t\t\t\thashcpy(mp->base, p->one->oid.hash);\n \t\t\t} else\n \t\t\t\tassert(!\"Invalid existing change recorded\");\n \t\t} else {\n \t\t\thashcpy(mp->obj, obj);\n-\t\t\thashcpy(mp->base, p->one->sha1);\n+\t\t\thashcpy(mp->base, p->one->oid.hash);\n \t\t\thashcpy(mp->local, uninitialized);\n-\t\t\thashcpy(mp->remote, p->two->sha1);\n+\t\t\thashcpy(mp->remote, p->two->oid.hash);\n \t\t\tlen++;\n \t\t}\n \t\ttrace_printf(\"\\t\\tStored remote change for %s: %.7s -> %.7s\\n\",\n@@ -203,21 +203,21 @@ static void diff_tree_local(struct notes_merge_options *o,\n \t\tif (verify_notes_filepair(p, obj)) {\n \t\t\ttrace_printf(\"\\t\\tCannot merge entry '%s' (%c): \"\n \t\t\t       \"%.7s -> %.7s. Skipping!\\n\", p->one->path,\n-\t\t\t       p->status, sha1_to_hex(p->one->sha1),\n-\t\t\t       sha1_to_hex(p->two->sha1));\n+\t\t\t       p->status, oid_to_hex(&p->one->oid),\n+\t\t\t       oid_to_hex(&p->two->oid));\n \t\t\tcontinue;\n \t\t}\n \t\tmp = find_notes_merge_pair_pos(changes, len, obj, 0, &match);\n \t\tif (!match) {\n \t\t\ttrace_printf(\"\\t\\tIgnoring local-only change for %s: \"\n \t\t\t       \"%.7s -> %.7s\\n\", sha1_to_hex(obj),\n-\t\t\t       sha1_to_hex(p->one->sha1),\n-\t\t\t       sha1_to_hex(p->two->sha1));\n+\t\t\t       oid_to_hex(&p->one->oid),\n+\t\t\t       oid_to_hex(&p->two->oid));\n \t\t\tcontinue;\n \t\t}\n \n \t\tassert(!hashcmp(mp->obj, obj));\n-\t\tif (is_null_sha1(p->two->sha1)) { /* deletion */\n+\t\tif (is_null_oid(&p->two->oid)) { /* deletion */\n \t\t\t/*\n \t\t\t * Either this is a true deletion (1), or it is part\n \t\t\t * of an A/D pair (2), or D/A pair (3):\n@@ -229,7 +229,7 @@ static void diff_tree_local(struct notes_merge_options *o,\n \t\t\t */\n \t\t\tif (!hashcmp(mp->local, uninitialized))\n \t\t\t\thashclr(mp->local);\n-\t\t} else if (is_null_sha1(p->one->sha1)) { /* addition */\n+\t\t} else if (is_null_oid(&p->one->oid)) { /* addition */\n \t\t\t/*\n \t\t\t * Either this is a true addition (1), or it is part\n \t\t\t * of an A/D pair (2), or D/A pair (3):\n@@ -240,16 +240,16 @@ static void diff_tree_local(struct notes_merge_options *o,\n \t\t\t */\n \t\t\tassert(is_null_sha1(mp->local) ||\n \t\t\t       !hashcmp(mp->local, uninitialized));\n-\t\t\thashcpy(mp->local, p->two->sha1);\n+\t\t\thashcpy(mp->local, p->two->oid.hash);\n \t\t} else { /* modification */\n \t\t\t/*\n \t\t\t * This is a true modification. p->one->sha1 shall\n \t\t\t * match mp->base, and mp->local shall be uninitialized.\n \t\t\t * Set mp->local to p->two->sha1.\n \t\t\t */\n-\t\t\tassert(!hashcmp(p->one->sha1, mp->base));\n+\t\t\tassert(!hashcmp(p->one->oid.hash, mp->base));\n \t\t\tassert(!hashcmp(mp->local, uninitialized));\n-\t\t\thashcpy(mp->local, p->two->sha1);\n+\t\t\thashcpy(mp->local, p->two->oid.hash);\n \t\t}\n \t\ttrace_printf(\"\\t\\tStored local change for %s: %.7s -> %.7s\\n\",\n \t\t       sha1_to_hex(mp->obj), sha1_to_hex(mp->base),\ndiff --git a/submodule.c b/submodule.c\nindex 4532b11d..cdccf65c 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -445,7 +445,7 @@ static void collect_submodules_from_diff(struct diff_queue_struct *q,\n \t\tstruct diff_filepair *p = q->queue[i];\n \t\tif (!S_ISGITLINK(p->two->mode))\n \t\t\tcontinue;\n-\t\tif (submodule_needs_pushing(p->two->path, p->two->sha1))\n+\t\tif (submodule_needs_pushing(p->two->path, p->two->oid.hash))\n \t\t\tstring_list_insert(needs_pushing, p->two->path);\n \t}\n }\n@@ -577,7 +577,7 @@ static void submodule_collect_changed_cb(struct diff_queue_struct *q,\n \t\t\t * being moved around. */\n \t\t\tstruct string_list_item *path;\n \t\t\tpath = unsorted_string_list_lookup(&changed_submodule_paths, p->two->path);\n-\t\t\tif (!path && !is_submodule_commit_present(p->two->path, p->two->sha1))\n+\t\t\tif (!path && !is_submodule_commit_present(p->two->path, p->two->oid.hash))\n \t\t\t\tstring_list_append(&changed_submodule_paths, xstrdup(p->two->path));\n \t\t} else {\n \t\t\t/* Submodule is new or was moved here */\ndiff --git a/wt-status.c b/wt-status.c\nindex 4f27bd62..7c2fa8cd 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -432,7 +432,8 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,\n \t\t\td->worktree_status = p->status;\n \t\td->dirty_submodule = p->two->dirty_submodule;\n \t\tif (S_ISGITLINK(p->two->mode))\n-\t\t\td->new_submodule_commits = !!hashcmp(p->one->sha1, p->two->sha1);\n+\t\t\td->new_submodule_commits = !!oidcmp(&p->one->oid,\n+\t\t\t\t\t\t\t    &p->two->oid);\n \t}\n }\n \n"},{"id":"289592","messageId":"20160618221407.1046188-2-sandals@crustytoothpaste.net","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"[PATCH v2 1/8] Add basic Coccinelle transforms.","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-18T22:14:00Z","receivedAt":"2016-06-18T22:14:41Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Coccinelle (http://coccinelle.lip6.fr/) is a program which performs\nmechanical transformations on C programs using semantic patches.  These\nsemantic patches can be used to implement automatic refactoring and\nmaintenance tasks.\n\nAdd a set of basic semantic patches to convert common patterns related\nto the struct object_id transformation, as well as a README.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n contrib/examples/coccinelle/README          |  2 +\n contrib/examples/coccinelle/object_id.cocci | 83 +++++++++++++++++++++++++++++\n 2 files changed, 85 insertions(+)\n create mode 100644 contrib/examples/coccinelle/README\n create mode 100644 contrib/examples/coccinelle/object_id.cocci\n\ndiff --git a/contrib/examples/coccinelle/README b/contrib/examples/coccinelle/README\nnew file mode 100644\nindex 00000000..9c2f8879\n--- /dev/null\n+++ b/contrib/examples/coccinelle/README\n@@ -0,0 +1,2 @@\n+This directory provides examples of Coccinelle (http://coccinelle.lip6.fr/)\n+semantic patches that might be useful to developers.\ndiff --git a/contrib/examples/coccinelle/object_id.cocci b/contrib/examples/coccinelle/object_id.cocci\nnew file mode 100644\nindex 00000000..0f068252\n--- /dev/null\n+++ b/contrib/examples/coccinelle/object_id.cocci\n@@ -0,0 +1,83 @@\n+@@\n+expression E1;\n+@@\n+- is_null_sha1(E1.hash)\n++ is_null_oid(&E1)\n+\n+@@\n+expression E1;\n+@@\n+- is_null_sha1(E1->hash)\n++ is_null_oid(E1)\n+\n+@@\n+expression E1;\n+@@\n+- sha1_to_hex(E1.hash)\n++ oid_to_hex(&E1)\n+\n+@@\n+expression E1;\n+@@\n+- sha1_to_hex(E1->hash)\n++ oid_to_hex(E1)\n+\n+@@\n+expression E1;\n+@@\n+- hashclr(E1.hash)\n++ oidclr(&E1)\n+\n+@@\n+expression E1;\n+@@\n+- hashclr(E1->hash)\n++ oidclr(E1)\n+\n+@@\n+expression E1, E2;\n+@@\n+- hashcmp(E1.hash, E2.hash)\n++ oidcmp(&E1, &E2)\n+\n+@@\n+expression E1, E2;\n+@@\n+- hashcmp(E1->hash, E2->hash)\n++ oidcmp(E1, E2)\n+\n+@@\n+expression E1, E2;\n+@@\n+- hashcmp(E1->hash, E2.hash)\n++ oidcmp(E1, &E2)\n+\n+@@\n+expression E1, E2;\n+@@\n+- hashcmp(E1.hash, E2->hash)\n++ oidcmp(&E1, E2)\n+\n+@@\n+expression E1, E2;\n+@@\n+- hashcpy(E1.hash, E2.hash)\n++ oidcpy(&E1, &E2)\n+\n+@@\n+expression E1, E2;\n+@@\n+- hashcpy(E1->hash, E2->hash)\n++ oidcpy(E1, E2)\n+\n+@@\n+expression E1, E2;\n+@@\n+- hashcpy(E1->hash, E2.hash)\n++ oidcpy(E1, &E2)\n+\n+@@\n+expression E1, E2;\n+@@\n+- hashcpy(E1.hash, E2->hash)\n++ oidcpy(&E1, E2)\n"},{"id":"289614","messageId":"57665CC6.6070208@kdbg.org","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"Re: [PATCH v2 0/8] object_id part 4","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2016-06-19T08:50:14Z","receivedAt":"2016-06-19T08:50:25Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 19.06.2016 um 00:13 schrieb brian m. carlson:\n> * Adjust the Coccinelle patches to transform plain structs before\n>    pointers to structs to avoid misconversions.  This addresses the issue\n>    that Peff caught originally.\n\nTo avoid future mistakes, can you write down how \"transform plain \nstructs before pointers to structs\" looks like? Is it a particular order \nof Coccinelle rules? Which part of the interdiff between the previous \nround and this round makes the difference?\n\nOn a tangent, I wondered recently, why we need oidcpy() and oidclr(). \nAfter all, in place of, e.g.,\n\n\toidcpy(&pair->two->oid, &p->oid);\n\toidclr(&one->oid);\n\nwe can write\n\n\tpair->two->oid = p->oid;\n\tone->oid = null_oid;\n\nIs there a particular reason *not* to make this transition? I find the \nlatter less cluttered with equal clarity.\n\n-- Hannes\n\n"},{"id":"289615","messageId":"20160619092448.GA12221@sigill.intra.peff.net","threadId":"42656","inReplyTo":"57665CC6.6070208@kdbg.org","subject":"Re: [PATCH v2 0/8] object_id part 4","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-06-19T09:24:48Z","receivedAt":"2016-06-19T09:24:58Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Jun 19, 2016 at 10:50:14AM +0200, Johannes Sixt wrote:\n\n> Am 19.06.2016 um 00:13 schrieb brian m. carlson:\n> > * Adjust the Coccinelle patches to transform plain structs before\n> >    pointers to structs to avoid misconversions.  This addresses the issue\n> >    that Peff caught originally.\n> \n> To avoid future mistakes, can you write down how \"transform plain structs\n> before pointers to structs\" looks like? Is it a particular order of\n> Coccinelle rules? Which part of the interdiff between the previous round and\n> this round makes the difference?\n\nYeah, I'd also like a better understanding of what went wrong in the\noriginal (just to be able to better evaluate the tool).\n\nAlso, for the record, the issue was noticed by Johannes originally, not\nme, as indicated above (I just found a similar case after seeing his\nreport).\n\n> On a tangent, I wondered recently, why we need oidcpy() and oidclr(). After\n> all, in place of, e.g.,\n> \n> \toidcpy(&pair->two->oid, &p->oid);\n> \toidclr(&one->oid);\n> \n> we can write\n> \n> \tpair->two->oid = p->oid;\n> \tone->oid = null_oid;\n> \n> Is there a particular reason *not* to make this transition? I find the\n> latter less cluttered with equal clarity.\n\nI think traditionally we've avoided struct assignment because some\nancient compilers didn't do it. But it's in C89, and I suspect it's\ncrept into the code base anyway over the years without anyone\ncomplaining.\n\n-Peff\n"},{"id":"289631","messageId":"20160619172538.GA16194@vauxhall.crustytoothpaste.net","threadId":"42656","inReplyTo":"20160619092448.GA12221@sigill.intra.peff.net","subject":"Re: [PATCH v2 0/8] object_id part 4","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-19T17:25:39Z","receivedAt":"2016-06-19T17:25:50Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Sun, Jun 19, 2016 at 05:24:48AM -0400, Jeff King wrote:\n> On Sun, Jun 19, 2016 at 10:50:14AM +0200, Johannes Sixt wrote:\n> > To avoid future mistakes, can you write down how \"transform plain structs\n> > before pointers to structs\" looks like? Is it a particular order of\n> > Coccinelle rules? Which part of the interdiff between the previous round and\n> > this round makes the difference?\n> \n> Yeah, I'd also like a better understanding of what went wrong in the\n> original (just to be able to better evaluate the tool).\n\nI'm not completely clear on why Coccinelle made the transform that it\ndid.  If you look at the commit messages, the new patch is this:\n\n  @@\n  struct diff_filespec o;\n  @@\n  - o.sha1\n  + o.oid.hash\n\n  @@\n  struct diff_filespec *p;\n  @@\n  - p->sha1\n  + p->oid.hash\n\nwhereas the two pieces were reversed before.  This fixes the problem\nbecause it's never possible for the second transform to match after the\nfirst has transformed a given piece of code.  The functional interdiff\nshows that only the issues the two of you found are changed.\n\n> Also, for the record, the issue was noticed by Johannes originally, not\n> me, as indicated above (I just found a similar case after seeing his\n> report).\n\nI apologize for the misattribution.\n\n> > On a tangent, I wondered recently, why we need oidcpy() and oidclr(). After\n> > all, in place of, e.g.,\n> > \n> > \toidcpy(&pair->two->oid, &p->oid);\n> > \toidclr(&one->oid);\n> > \n> > we can write\n> > \n> > \tpair->two->oid = p->oid;\n> > \tone->oid = null_oid;\n> > \n> > Is there a particular reason *not* to make this transition? I find the\n> > latter less cluttered with equal clarity.\n> \n> I think traditionally we've avoided struct assignment because some\n> ancient compilers didn't do it. But it's in C89, and I suspect it's\n> crept into the code base anyway over the years without anyone\n> complaining.\n\nI asked about this earlier and Junio felt that struct assignment was\nless desirable.\n\nAlso, if we do struct assignment, if we add a new hash, we may copy more\nthan necessary (e.g. 64 bytes when we're only using SHA-1); however,\nthis may be offset by the ability of the compiler to compute the offset\nat compile time.\n-- \nbrian m. carlson / brian with sandals: Houston, Texas, US\n+1 832 623 2791 | https://www.crustytoothpaste.net/~bmc | My opinion only\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"289657","messageId":"alpine.DEB.2.20.1606200853580.22630@virtualbox","threadId":"42656","inReplyTo":"20160619092448.GA12221@sigill.intra.peff.net","subject":"Re: [PATCH v2 0/8] object_id part 4","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-06-20T07:01:30Z","receivedAt":"2016-06-20T07:02:15Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Peff,\n\nOn Sun, 19 Jun 2016, Jeff King wrote:\n\n> I think traditionally we've avoided struct assignment because some\n> ancient compilers didn't do it. But it's in C89, and I suspect it's\n> crept into the code base anyway over the years without anyone\n> complaining.\n\nI fear that's my fault, at least partially, seeing as merge-recursive.c\neven *returns* structs (see 6d297f81; I plan to fix that as part of the\ncleaned-up am-3-merge-recursive-direct patch series).\n\nSorry,\nDscho\n"},{"id":"289665","messageId":"20160620100522.GB14058@sigill.intra.peff.net","threadId":"42656","inReplyTo":"alpine.DEB.2.20.1606200853580.22630@virtualbox","subject":"Re: [PATCH v2 0/8] object_id part 4","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-06-20T10:05:23Z","receivedAt":"2016-06-20T10:12:23Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Jun 20, 2016 at 09:01:30AM +0200, Johannes Schindelin wrote:\n\n> On Sun, 19 Jun 2016, Jeff King wrote:\n> \n> > I think traditionally we've avoided struct assignment because some\n> > ancient compilers didn't do it. But it's in C89, and I suspect it's\n> > crept into the code base anyway over the years without anyone\n> > complaining.\n> \n> I fear that's my fault, at least partially, seeing as merge-recursive.c\n> even *returns* structs (see 6d297f81; I plan to fix that as part of the\n> cleaned-up am-3-merge-recursive-direct patch series).\n\nHeh, that commit is quite old. If nobody has complained about it, then I\nthink there is nothing to be sorry about. If struct assignment (and\nreturns) work everywhere, and they make the code easier to read, we\nshould be using them.\n\nI am on the fence regarding oidcpy/oidclr. I agree they _could_ be\nstruct assignments, but it is also convenient to have concept wrapped up\nin a function, in case we ever want to do anything more complicated.\n\n-Peff\n"},{"id":"289679","messageId":"xmqq8txzvour.fsf@gitster.mtv.corp.google.com","threadId":"42656","inReplyTo":"20160620100522.GB14058@sigill.intra.peff.net","subject":"Re: [PATCH v2 0/8] object_id part 4","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-06-20T15:53:16Z","receivedAt":"2016-06-20T16:01:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> I am on the fence regarding oidcpy/oidclr. I agree they _could_ be\n> struct assignments, but it is also convenient to have concept wrapped up\n> in a function, in case we ever want to do anything more complicated.\n\nAlso dedicated functions have documenation value.  There are some\nthings that currently use the same 40-hex that is the result of\nrunning SHA-1 but are not object names (e.g.  patch id, and rerere\nid).  They use the same hashcpy()/hashcmp() helpers as object names\ndo, but the code that use them probably do not want to be converted\nto struct oid and oidcpy().\n\n"},{"id":"289813","messageId":"xmqqy45ynsnp.fsf@gitster.mtv.corp.google.com","threadId":"42656","inReplyTo":"20160618221407.1046188-1-sandals@crustytoothpaste.net","subject":"Re: [PATCH v2 0/8] object_id part 4","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-06-21T21:22:50Z","receivedAt":"2016-06-21T21:29:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> This series is part 4 in a series of conversions to replace instances of\n> unsigned char [20] with struct object_id.  Most of this series touches\n> the merge-recursive code.\n\nI've queued them in 'pu', but please read contrib/examples/README\n;-) Tentatively, I used contrib/coccinelle instead, but something\neven shorter (e.g. contrib/cocci) might be sufficient.\n\n> Note that in the patches created with the semantic patches, the only manual\n> change was the definition of the struct member.  Opinions on whether this is a\n> viable technique for further work to ease both the creation and review of\n> patches are of course welcomed.\n\nThanks.\n"},{"id":"289817","messageId":"xmqqtwgmns0r.fsf@gitster.mtv.corp.google.com","threadId":"42656","inReplyTo":"20160618221407.1046188-3-sandals@crustytoothpaste.net","subject":"Re: [PATCH v2 2/8] Apply object_id Coccinelle transformations.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-06-21T21:36:36Z","receivedAt":"2016-06-21T21:37:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> Apply the set of semantic patches from contrib/examples/coccinelle to\n> convert some leftover places using struct object_id's hash member to\n> instead use the wrapper functions that take struct object_id natively.\n\nIt is somewhat curious how these 'some leftover places' are chosen.\n\nEspecially, this hunk was interesting.\n\n> diff --git a/refs/files-backend.c b/refs/files-backend.c\n> index 1f380764..dac3a222 100644\n> --- a/refs/files-backend.c\n> +++ b/refs/files-backend.c\n> @@ -1725,14 +1725,14 @@ static int verify_lock(struct ref_lock *lock,\n>  \t\t\terrno = save_errno;\n>  \t\t\treturn -1;\n>  \t\t} else {\n> -\t\t\thashclr(lock->old_oid.hash);\n> +\t\t\toidclr(&lock->old_oid);\n>  \t\t\treturn 0;\n>  \t\t}\n>  \t}\n>  \tif (old_sha1 && hashcmp(lock->old_oid.hash, old_sha1)) {\n>  \t\tstrbuf_addf(err, \"ref %s is at %s but expected %s\",\n>  \t\t\t    lock->ref_name,\n> -\t\t\t    sha1_to_hex(lock->old_oid.hash),\n> +\t\t\t    oid_to_hex(&lock->old_oid),\n>  \t\t\t    sha1_to_hex(old_sha1));\n>  \t\terrno = EBUSY;\n>  \t\treturn -1;\n\nThe function gets old_sha1 which is the old-world \"const unsigned\nchar *\" that is passed via lock_ref_sha1_basic() from public entry\npoints like rename_ref() and ref_transaction_commit().  As this\ncodepath and the functions involved have not be converted to oid,\nwe end up seeing oid_to_hex() next to sha1_to_hex() ;-)\n\nNot a complaint; this is how we make progress incrementally.\n\nIt was just I noticed this function is left in a somewhat funny\nintermediate state after this step.\n\nThanks.\n"},{"id":"289818","messageId":"xmqqmvmenpwz.fsf@gitster.mtv.corp.google.com","threadId":"42656","inReplyTo":"20160618221407.1046188-4-sandals@crustytoothpaste.net","subject":"Re: [PATCH v2 3/8] Convert struct diff_filespec to struct object_id","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-06-21T22:22:04Z","receivedAt":"2016-06-21T22:22:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\nI was trying to make sure there is no misconversion, but some lines\nthat got wrapped were distracting.  For example:\n\n> @@ -2721,7 +2722,8 @@ static int diff_populate_gitlink(struct diff_filespec *s, int size_only)\n>  \tif (s->dirty_submodule)\n>  \t\tdirty = \"-dirty\";\n>  \n> -\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\", sha1_to_hex(s->sha1), dirty);\n> +\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\",\n> +\t\t    oid_to_hex(&s->oid), dirty);\n\nThis would have been\n\n> -\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\", sha1_to_hex(s->sha1), dirty);\n> +\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\", oid_to_hex(&s->oid), dirty);\n\nwhich the conversion made the line _shorter_.  If the original's\nline length was acceptable, there is no reason to wrap the result.\n\n> -\t\t\t\tdie(\"unable to read %s\", sha1_to_hex(s->sha1));\n> +\t\t\t\tdie(\"unable to read %s\",\n> +\t\t\t\t    oid_to_hex(&s->oid));\n\nLikewise.\n\n> @@ -2937,7 +2940,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n>  \t\t\tif (!one->sha1_valid)\n>  \t\t\t\tsha1_to_hex_r(temp->hex, null_sha1);\n>  \t\t\telse\n> -\t\t\t\tsha1_to_hex_r(temp->hex, one->sha1);\n> +\t\t\t\tsha1_to_hex_r(temp->hex, one->oid.hash);\n\nThis suggests that oid_to_hex_r() is needed, perhaps?\n\n> @@ -2952,7 +2955,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n>  \t\tif (diff_populate_filespec(one, 0))\n>  \t\t\tdie(\"cannot read data blob for %s\", one->path);\n>  \t\tprep_temp_blob(name, temp, one->data, one->size,\n> -\t\t\t       one->sha1, one->mode);\n> +\t\t\t       one->oid.hash, one->mode);\n\nprep_temp_blob() is a file-scope static with only two callers.  It\nprobably would not take too much effort to make it take &one->oid\ninstead?\n\n> @@ -3075,8 +3078,8 @@ static void fill_metainfo(struct strbuf *msg,\n>  \t\t\t\tabbrev = 40;\n>  \t\t}\n>  \t\tstrbuf_addf(msg, \"%s%sindex %s..\", line_prefix, set,\n> -\t\t\t    find_unique_abbrev(one->sha1, abbrev));\n> -\t\tstrbuf_addstr(msg, find_unique_abbrev(two->sha1, abbrev));\n> +\t\t\t    find_unique_abbrev(one->oid.hash, abbrev));\n> +\t\tstrbuf_addstr(msg, find_unique_abbrev(two->oid.hash, abbrev));\n\nGood.  As more and more callers of find_unique_abbrev() is converted\nto pass oid.hash to it, eventually we will have only a handful of\ncallers that have a raw \"const unsigned char sha1[20]\" to pass it,\nand we can eventually make the function take &oid.  It seems we are\nnot quite there yet, by the looks of 'git grep find_unique_abbrev'\noutput, but we are getting closer.\n\n> @@ -3134,17 +3137,17 @@ static void diff_fill_sha1_info(struct diff_filespec *one)\n>  \t\tif (!one->sha1_valid) {\n>  \t\t\tstruct stat st;\n>  \t\t\tif (one->is_stdin) {\n> -\t\t\t\thashcpy(one->sha1, null_sha1);\n> +\t\t\t\thashcpy(one->oid.hash, null_sha1);\n>  \t\t\t\treturn;\n>  \t\t\t}\n\noidclr()?\n\nPerhaps a preparatory step of\n\n\tunsigned char *E1;\n\n\t-hashcpy(E1, null_sha1);\n        +hashclr(E1)\n\nwould help?\n\n> @@ -902,13 +904,13 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n>  \t\tresult.clean = 0;\n>  \t\tif (S_ISREG(a->mode)) {\n>  \t\t\tresult.mode = a->mode;\n> -\t\t\thashcpy(result.sha, a->sha1);\n> +\t\t\thashcpy(result.sha, a->oid.hash);\n>  \t\t} else {\n>  \t\t\tresult.mode = b->mode;\n> -\t\t\thashcpy(result.sha, b->sha1);\n> +\t\t\thashcpy(result.sha, b->oid.hash);\n\nmerge_file_info is a file-scope-static type, and it shouldn't take\ntoo much effort to replace its sha1 with an oid, I would think.\n\n> -\t\tif (!sha_eq(a->sha1, one->sha1) && !sha_eq(b->sha1, one->sha1))\n> +\t\tif (!sha_eq(a->oid.hash, one->oid.hash) && !sha_eq(b->oid.hash, one->oid.hash))\n\nsha_eq() knows that either of its two parameters could be NULL, but\na->sha1 is diff_filespec.sha1 which cannot be NULL.\n\nSo !sha_eq() here can become oidcmp().  There are some calls to\nsha_eq() that could pass NULL (e.g. a_sha could be NULL in\nblob_unchanged()), but many other sha_eq() can become !oidcmp().\n\nAm I reading the conversion correctly?\n\nI'll stop here for now and will come back to the remainder of this\npatch sometime later.  Thanks.\n\n> diff --git a/notes-merge.c b/notes-merge.c\n> index 34bfac0c..62c23d8a 100644\n> --- a/notes-merge.c\n> +++ b/notes-merge.c\n"},{"id":"289884","messageId":"20160622184431.GA8937@vauxhall.crustytoothpaste.net","threadId":"42656","inReplyTo":"xmqqy45ynsnp.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 0/8] object_id part 4","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-22T18:44:31Z","receivedAt":"2016-06-22T18:44:42Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, Jun 21, 2016 at 02:22:50PM -0700, Junio C Hamano wrote:\n> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n> \n> > This series is part 4 in a series of conversions to replace instances of\n> > unsigned char [20] with struct object_id.  Most of this series touches\n> > the merge-recursive code.\n> \n> I've queued them in 'pu', but please read contrib/examples/README\n> ;-) Tentatively, I used contrib/coccinelle instead, but something\n> even shorter (e.g. contrib/cocci) might be sufficient.\n\nThat seems fine with me.  I did read contrib/examples/README, but\nfigured it might be okay nevertheless.  I think contrib/coccinelle is\nbetter, though.\n-- \nbrian m. carlson / brian with sandals: Houston, Texas, US\n+1 832 623 2791 | https://www.crustytoothpaste.net/~bmc | My opinion only\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"290022","messageId":"20160624152742.GA10808@vauxhall.crustytoothpaste.net","threadId":"42656","inReplyTo":"xmqqmvmenpwz.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 3/8] Convert struct diff_filespec to struct object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2016-06-24T15:27:42Z","receivedAt":"2016-06-24T15:28:01Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, Jun 21, 2016 at 03:22:04PM -0700, Junio C Hamano wrote:\n> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n> \n> I was trying to make sure there is no misconversion, but some lines\n> that got wrapped were distracting.  For example:\n> \n> > @@ -2721,7 +2722,8 @@ static int diff_populate_gitlink(struct diff_filespec *s, int size_only)\n> >  \tif (s->dirty_submodule)\n> >  \t\tdirty = \"-dirty\";\n> >  \n> > -\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\", sha1_to_hex(s->sha1), dirty);\n> > +\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\",\n> > +\t\t    oid_to_hex(&s->oid), dirty);\n> \n> This would have been\n> \n> > -\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\", sha1_to_hex(s->sha1), dirty);\n> > +\tstrbuf_addf(&buf, \"Subproject commit %s%s\\n\", oid_to_hex(&s->oid), dirty);\n> \n> which the conversion made the line _shorter_.  If the original's\n> line length was acceptable, there is no reason to wrap the result.\n\nI do tend to agree.  Coccinelle wrapped the line automatically, but I'm\nnot sure why it did that.  I can see if there's an option that disables\nthat if you'd like.  I'm a bit reticent to manually fix up the line\nwrapping as I want others to be able to run Coccinelle themselves and\nget identical output.\n\n> > @@ -2937,7 +2940,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n> >  \t\t\tif (!one->sha1_valid)\n> >  \t\t\t\tsha1_to_hex_r(temp->hex, null_sha1);\n> >  \t\t\telse\n> > -\t\t\t\tsha1_to_hex_r(temp->hex, one->sha1);\n> > +\t\t\t\tsha1_to_hex_r(temp->hex, one->oid.hash);\n> \n> This suggests that oid_to_hex_r() is needed, perhaps?\n\nProbably so.  I can add that in a reroll.\n\n> > @@ -2952,7 +2955,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,\n> >  \t\tif (diff_populate_filespec(one, 0))\n> >  \t\t\tdie(\"cannot read data blob for %s\", one->path);\n> >  \t\tprep_temp_blob(name, temp, one->data, one->size,\n> > -\t\t\t       one->sha1, one->mode);\n> > +\t\t\t       one->oid.hash, one->mode);\n> \n> prep_temp_blob() is a file-scope static with only two callers.  It\n> probably would not take too much effort to make it take &one->oid\n> instead?\n\nI can certainly do that in a reroll.\n\n> > @@ -3075,8 +3078,8 @@ static void fill_metainfo(struct strbuf *msg,\n> >  \t\t\t\tabbrev = 40;\n> >  \t\t}\n> >  \t\tstrbuf_addf(msg, \"%s%sindex %s..\", line_prefix, set,\n> > -\t\t\t    find_unique_abbrev(one->sha1, abbrev));\n> > -\t\tstrbuf_addstr(msg, find_unique_abbrev(two->sha1, abbrev));\n> > +\t\t\t    find_unique_abbrev(one->oid.hash, abbrev));\n> > +\t\tstrbuf_addstr(msg, find_unique_abbrev(two->oid.hash, abbrev));\n> \n> Good.  As more and more callers of find_unique_abbrev() is converted\n> to pass oid.hash to it, eventually we will have only a handful of\n> callers that have a raw \"const unsigned char sha1[20]\" to pass it,\n> and we can eventually make the function take &oid.  It seems we are\n> not quite there yet, by the looks of 'git grep find_unique_abbrev'\n> output, but we are getting closer.\n\nYes, I'd noticed that as well.  One thing I observed from these\nconversions is that it sometimes takes a huge amount of work to get all\nthe callers to change.  Often, it's only one or two call sites that end\nup being a bunch of work.\n\n> > @@ -3134,17 +3137,17 @@ static void diff_fill_sha1_info(struct diff_filespec *one)\n> >  \t\tif (!one->sha1_valid) {\n> >  \t\t\tstruct stat st;\n> >  \t\t\tif (one->is_stdin) {\n> > -\t\t\t\thashcpy(one->sha1, null_sha1);\n> > +\t\t\t\thashcpy(one->oid.hash, null_sha1);\n> >  \t\t\t\treturn;\n> >  \t\t\t}\n> \n> oidclr()?\n> \n> Perhaps a preparatory step of\n> \n> \tunsigned char *E1;\n> \n> \t-hashcpy(E1, null_sha1);\n>         +hashclr(E1)\n> \n> would help?\n\nSure.  I can do that.\n\n> > @@ -902,13 +904,13 @@ static struct merge_file_info merge_file_1(struct merge_options *o,\n> >  \t\tresult.clean = 0;\n> >  \t\tif (S_ISREG(a->mode)) {\n> >  \t\t\tresult.mode = a->mode;\n> > -\t\t\thashcpy(result.sha, a->sha1);\n> > +\t\t\thashcpy(result.sha, a->oid.hash);\n> >  \t\t} else {\n> >  \t\t\tresult.mode = b->mode;\n> > -\t\t\thashcpy(result.sha, b->sha1);\n> > +\t\t\thashcpy(result.sha, b->oid.hash);\n> \n> merge_file_info is a file-scope-static type, and it shouldn't take\n> too much effort to replace its sha1 with an oid, I would think.\n\nThat's one of the following patches.\n\n> sha_eq() knows that either of its two parameters could be NULL, but\n> a->sha1 is diff_filespec.sha1 which cannot be NULL.\n> \n> So !sha_eq() here can become oidcmp().  There are some calls to\n> sha_eq() that could pass NULL (e.g. a_sha could be NULL in\n> blob_unchanged()), but many other sha_eq() can become !oidcmp().\n> \n> Am I reading the conversion correctly?\n\nI think that's accurate.  I'll make that change.\n-- \nbrian m. carlson / brian with sandals: Houston, Texas, US\n+1 832 623 2791 | https://www.crustytoothpaste.net/~bmc | My opinion only\nOpenPGP: https://keybase.io/bk2204\n"}]}