)]}'
{
  "commit": "5b174e060e6b0940821c3aabca20817defe05867",
  "tree": "e56bdb4b6f2a2225d582f24ae9ad3f141fa94191",
  "parents": [
    "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
  ],
  "author": {
    "name": "Joe Tsai",
    "email": "joetsai@digital-static.net",
    "time": "Fri Jul 14 16:28:15 2017 -0700"
  },
  "committer": {
    "name": "Joe Tsai",
    "email": "joetsai@digital-static.net",
    "time": "Wed Aug 09 09:31:05 2017 -0700"
  },
  "message": "Add Options to prioritize some set of options over another\n\nAdded API:\n\tDefault() Option\n\tFilterPriority(opts ...Option) Option\n\nFilterPriority returns a new Option where an option, opts[i],\nis only evaluated if no fundamental options remain after applying all filters\nin all prior options, opts[:i].\n\nIn order to prevent further options from being evaluated, the Default option\ncan be used to ensure that some fundamental option remains.\n\nSuppose you have a value tree T, where T1 and T2 are sub-trees within T.\nPrior to the addition of FilterPriority, it was impossible to do certain things.\n\nExample 1: You could not make the following compose together nicely.\n\t* Have a set of options OT1 to affect only values under T1.\n\t* Have a set of options OT2 to affect only values under T2.\n\t* Have a set of options OT to affect only T, but not values under T1 and T2.\n\t* Have a set of options O to affect all other values, but no those in T\n\t  (and by extension those in T1 and T2).\nSolution 1:\n\tFilterPriority(\n\t\t// Since T1 and T2 do not overlap, they could be placed within the\n\t\t// same priority level by grouping them in an Options group.\n\t\tFilterTree(T1, OT1),\n\t\tFilterTree(T2, OT2),\n\t\tFilterTree(T, OT),\n\t\tO,\n\t)\n\nExample 2: You could not make the following compose together nicely.\n\t* Have a set of options O apply on all nodes except those in T1 and T2.\n\t* Instead, we want the default behavior of cmp on T1 and T2.\nSolution 2:\n\tFilterPriority(\n\t\t// Here we show how to group T1 and T2 together to be on the same\n\t\t// priority level.\n\t\tOptions{\n\t\t\tFilterTree(T1, Default()),\n\t\t\tFilterTree(T2, Default()),\n\t\t},\n\t\tO,\n\t)\n\nExample 3: You have this: type MyStruct struct { *pb.MyMessage; ... }\n\t* Generally, you want to use Comparer(proto.Equal) to ensure\n\t  that all proto.Messages within the struct are properly compared.\n\t  However, this type has an embedded proto (generally a bad idea),\n\t  which causes the MyStruct to satisfy the proto.Message interface\n\t  and unintentionally causes Equal to use proto.Equal on MyStruct,\n\t  which crashes.\n\t* How can you have Comparer(proto.Equal) apply to all other\n\t  proto.Message without applying just to MyStruct?\nSolution 3:\n\tFilterPriority(\n\t\t// Only for MyStruct, use the default behavior of Equal,\n\t\t// which is to recurse into the structure of MyStruct.\n\t\tFilterPath(func(p Path) bool {\n\t\t\treturn p.Last().Type() \u003d\u003d reflect.TypeOf(MyStruct{})\n\t\t}, Default()),\n\n\t\t// Use proto.Equal for all other cases of proto.Message.\n\t\tComparer(proto.Equal),\n\t)\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "5527f0149761ed5500614f805c93cd5b7a7bd138",
      "old_mode": 33188,
      "old_path": "cmp/compare.go",
      "new_id": "a62ce044383b0ebae15d4e64a7eeecd68f0bc17f",
      "new_mode": 33188,
      "new_path": "cmp/compare.go"
    },
    {
      "type": "modify",
      "old_id": "a4e159ac483ca0b8a457c2f018cf047a14369aa0",
      "old_mode": 33188,
      "old_path": "cmp/options.go",
      "new_id": "e3d6a706fab2aa7fb3b50d19e9515ee21c908727",
      "new_mode": 33188,
      "new_path": "cmp/options.go"
    }
  ]
}
